Passed
Push — main ( 14a1d4...970705 )
by Rafael
43:29
created

InstallController::_checkBrowser()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 19
rs 9.8333
1
<?php
2
3
/* Copyright (C) 2004-2007  Rodolphe Quiedeville    <[email protected]>
4
 * Copyright (C) 2004-2016  Laurent Destailleur     <[email protected]>
5
 * Copyright (C) 2004       Eric Seigne             <[email protected]>
6
 * Copyright (C) 2004       Benoit Mortier          <[email protected]>
7
 * Copyright (C) 2004       Sebastien DiCintio      <[email protected]>
8
 * Copyright (C) 2005       Marc Barilley / Ocebo   <[email protected]>
9
 * Copyright (C) 2005-2012  Regis Houssin           <[email protected]>
10
 * Copyright (C) 2013-2014  Juanjo Menent           <[email protected]>
11
 * Copyright (C) 2014       Marcos García           <[email protected]>
12
 * Copyright (C) 2015       Cedric GROSS            <[email protected]>
13
 * Copyright (C) 2015-2016  Raphaël Doursenaud      <[email protected]>
14
 * Copyright (C) 2024		MDW                     <[email protected]>
15
 * Copyright (C) 2024		Rafael San José         <[email protected]>
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 3 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29
 */
30
31
namespace DoliModules\Install\Controller;
32
33
use DoliCore\Base\Config;
34
use DoliCore\Base\DolibarrViewController;
35
use DoliCore\Form\FormAdmin;
36
use DoliModules\Install\Lib\Check;
37
use DoliModules\Install\Lib\Status;
38
use PDO;
39
40
require_once BASE_PATH . '/../Dolibarr/Lib/Admin.php';
41
require_once BASE_PATH . '/install/inc.php';
42
43
class InstallController extends DolibarrViewController
44
{
45
    /**
46
     * @var bool
47
     */
48
    public $allowInstall;
49
    /**
50
     * @var mixed
51
     */
52
    public $selectLang;
53
    /**
54
     * @var array
55
     */
56
    public $availableChoices;
57
    /**
58
     * @var false
59
     */
60
    public $errorMigrations;
61
62
    public $checks;
63
    public $nextButton;
64
    public $nextButtonJs;
65
    public $htmlComboLanguages;
66
    public $notAvailableChoices;
67
    public $printVersion;
68
    public $force_install_noedit;
69
    public $force_install_mainforcehttps;
70
    public $install_createdatabase;
71
    public $install_noedit;
72
    public $autofill;
73
    public $install_databaserootlogin;
74
75
    /**
76
     *  Create main file. No particular permissions are set by installer.
77
     *
78
     * @param string $mainfile Full path name of main file to generate/update
79
     * @param string $this ->main_dir Full path name to main.inc.php file
80
     *
81
     * @return void
82
     */
83
    function write_main_file($mainfile, $main_dir)
84
    {
85
        $fp = @fopen("$mainfile", "w");
86
        if ($fp) {
87
            clearstatcache();
88
            fwrite($fp, '<?php' . "\n");
89
            fwrite($fp, "// Wrapper to include main into htdocs\n");
90
            fwrite($fp, "include_once '" . $main_dir . "/main.inc.php';\n");
91
            fclose($fp);
92
        }
93
    }
94
95
    /**
96
     *  Create master file. No particular permissions are set by installer.
97
     *
98
     * @param string $masterfile Full path name of master file to generate/update
99
     * @param string $this ->main_dir   Full path name to master.inc.php file
100
     *
101
     * @return void
102
     */
103
    function write_master_file($masterfile, $main_dir)
104
    {
105
        $fp = @fopen("$masterfile", "w");
106
        if ($fp) {
107
            clearstatcache();
108
            fwrite($fp, '<?php' . "\n");
109
            fwrite($fp, "// Wrapper to include master into htdocs\n");
110
            fwrite($fp, "include_once '" . $main_dir . "/master.inc.php';\n");
111
            fclose($fp);
112
        }
113
    }
114
115
    public function _checkAction(): bool
116
    {
117
        if (parent::checkAction()) {
0 ignored issues
show
Bug introduced by
The method checkAction() does not exist on DoliCore\Base\DolibarrViewController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

117
        if (parent::/** @scrutinizer ignore-call */ checkAction()) {

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...
118
            return true;
119
        }
120
121
        switch (htmlentities($this->action)) {
122
            case 'checked':
123
                return $this->actionChecked();
0 ignored issues
show
Bug introduced by
The method actionChecked() does not exist on DoliModules\Install\Controller\InstallController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

123
                return $this->/** @scrutinizer ignore-call */ actionChecked();

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...
124
            case 'config':
125
                return $this->actionConfig();
0 ignored issues
show
Bug introduced by
The method actionConfig() does not exist on DoliModules\Install\Controller\InstallController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

125
                return $this->/** @scrutinizer ignore-call */ actionConfig();

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...
126
            case 'step2':
127
                return $this->actionStep2();
0 ignored issues
show
Bug introduced by
The method actionStep2() does not exist on DoliModules\Install\Controller\InstallController. Did you maybe mean _actionStep2()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

127
                return $this->/** @scrutinizer ignore-call */ actionStep2();

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...
128
            case $this->langs->trans("Start"):
129
                return $this->actionStart();
0 ignored issues
show
Bug introduced by
The method actionStart() does not exist on DoliModules\Install\Controller\InstallController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
                return $this->/** @scrutinizer ignore-call */ actionStart();

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...
130
            default:
131
                $this->syslog("The action $this->action is not defined!");
132
        }
133
134
        return false;
135
    }
136
137
    public function _actionStep2()
138
    {
139
        $step = 2;
140
        $ok = 0;
141
142
        $this->template = 'install/step2';
143
        $this->subtitle = $this->langs->trans("CreateDatabaseObjects");
144
        $this->nextButton = true;
145
146
// This page can be long. We increase the time allowed. / Cette page peut etre longue. On augmente le delai autorise.
147
// Only works if you are not in safe_mode. / Ne fonctionne que si on est pas en safe_mode.
148
149
        $err = error_reporting();
150
        error_reporting(0);      // Disable all errors
151
//error_reporting(E_ALL);
152
        @set_time_limit(1800);   // Need 1800 on some very slow OS like Windows 7/64
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

152
        /** @scrutinizer ignore-unhandled */ @set_time_limit(1800);   // Need 1800 on some very slow OS like Windows 7/64

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
153
        error_reporting($err);
154
155
        $action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : (empty($argv[1]) ? '' : $argv[1]);
156
        $setuplang = GETPOST('selectlang', 'aZ09', 3) ? GETPOST('selectlang', 'aZ09', 3) : (empty($argv[2]) ? 'auto' : $argv[2]);
157
158
        $conffile = Config::getDolibarrConfigFilename();
159
        $conf = Globals::getConfig();
160
        $this->conf = Globals::getConf();
161
162
// Choice of DBMS
163
        $choix = 0;
164
        if ($conf->main_db_type == "MySqliEngine") {
165
            $choix = 1;
166
        }
167
        if ($conf->main_db_type == "PgSqlEngine") {
168
            $choix = 2;
169
        }
170
        if ($conf->main_db_type == "mssql") {
171
            $choix = 3;
172
        }
173
        if ($conf->main_db_type == "sqlite") {
174
            $choix = 4;
175
        }
176
        if ($conf->main_db_type == "Sqlite3Engine") {
177
            $choix = 5;
178
        }
179
//if (empty($choix)) dol_print_error(null,'Database type '.$conf->main_db_type.' not supported into step2.php page');
180
181
182
// Now we load forced values from install.forced.php file.
183
184
        $useforcedwizard = false;
185
        $forcedfile = "./install.forced.php";
186
        if ($conffile == "/etc/dolibarr/conf.php") {
187
            $forcedfile = "/etc/dolibarr/install.forced.php";
188
        }
189
        if (@file_exists($forcedfile)) {
190
            $useforcedwizard = true;
191
            include_once $forcedfile;
192
            // test for travis
193
            if (!empty($argv[1]) && $argv[1] == "set") {
194
                $action = "set";
195
            }
196
        }
197
198
        dolibarr_install_syslog("--- step2: entering step2.php page");
199
200
201
        /*
202
         *  View
203
         */
204
205
// Test if we can run a first install process
206
        if (!is_writable($conffile)) {
207
            print $this->langs->trans("ConfFileIsNotWritable", $conffiletoshow);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $conffiletoshow does not exist. Did you maybe mean $conffile?
Loading history...
208
            pFooter(1, $setuplang, 'jscheckparam');
209
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
210
        }
211
212
        if ($action == "set") {
213
            print '<h3><img class="valignmiddle inline-block paddingright" src="../' . $this->config->main->theme . '/img/svg/database.svg" width="20" alt="Database"> ' . $this->langs->trans("Database") . '</h3>';
214
215
            print '<table cellspacing="0" style="padding: 4px 4px 4px 0" border="0" width="100%">';
216
            $error = 0;
217
218
            $db = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, (int)$conf->db->port);
219
220
            if ($db->connected) {
221
                print "<tr><td>";
222
                print $this->langs->trans("ServerConnection") . " : " . $conf->db->host . '</td><td><img src="../theme/eldy/img/ok.png" alt="Ok"></td></tr>';
223
                $ok = 1;
224
            } else {
225
                print "<tr><td>Failed to connect to server : " . $conf->db->host . '</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>';
226
            }
227
228
            if ($ok) {
229
                if ($db->database_selected) {
230
                    dolibarr_install_syslog("step2: successful connection to database: " . $conf->db->name);
231
                } else {
232
                    dolibarr_install_syslog("step2: failed connection to database :" . $conf->db->name, LOG_ERR);
233
                    print "<tr><td>Failed to select database " . $conf->db->name . '</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>';
234
                    $ok = 0;
235
                }
236
            }
237
238
239
            // Display version / Affiche version
240
            if ($ok) {
241
                $version = $db->getVersion();
242
                $versionarray = $db->getVersionArray();
243
                print '<tr><td>' . $this->langs->trans("DatabaseVersion") . '</td>';
244
                print '<td>' . $version . '</td></tr>';
245
                //print '<td class="right">'.join('.',$versionarray).'</td></tr>';
246
247
                print '<tr><td>' . $this->langs->trans("DatabaseName") . '</td>';
248
                print '<td>' . $db->database_name . '</td></tr>';
249
                //print '<td class="right">'.join('.',$versionarray).'</td></tr>';
250
            }
251
252
            $requestnb = 0;
253
254
            // To disable some code, so you can call step2 with url like
255
            // http://localhost/dolibarrnew/install/step2.php?action=set&token='.newToken().'&createtables=0&createkeys=0&createfunctions=0&createdata=llx_20_c_departements
256
            $createtables = GETPOSTISSET('createtables') ? GETPOST('createtables') : 1;
257
            $createkeys = GETPOSTISSET('createkeys') ? GETPOST('createkeys') : 1;
258
            $createfunctions = GETPOSTISSET('createfunctions') ? GETPOST('createfunction') : 1;
259
            $createdata = GETPOSTISSET('createdata') ? GETPOST('createdata') : 1;
260
261
262
            // To say that SQL we pass to query are already escaped for mysql, so we need to unescape them
263
            if (property_exists($db, 'unescapeslashquot')) {
264
                $db->unescapeslashquot = true;
265
            }
266
267
            /**************************************************************************************
268
             *
269
             * Load files tables/*.sql (not the *.key.sql). Files with '-xxx' in name are excluded (they will be loaded during activation of module 'xxx').
270
             * To do before the files *.key.sql
271
             *
272
             ***************************************************************************************/
273
            if ($ok && $createtables) {
274
                // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax)
275
                $dir = "mysql/tables/";
276
277
                $ok = 0;
278
                $handle = opendir($dir);
279
                dolibarr_install_syslog("step2: open tables directory " . $dir . " handle=" . $handle);
280
                $tablefound = 0;
281
                $tabledata = [];
282
                if (is_resource($handle)) {
283
                    while (($file = readdir($handle)) !== false) {
284
                        if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file) && !preg_match('/\.key\.sql$/i', $file) && !preg_match('/\-/', $file)) {
285
                            $tablefound++;
286
                            $tabledata[] = $file;
287
                        }
288
                    }
289
                    closedir($handle);
290
                }
291
292
                // Sort list of sql files on alphabetical order (load order is important)
293
                sort($tabledata);
294
                foreach ($tabledata as $file) {
295
                    $name = substr($file, 0, dol_strlen($file) - 4);
296
                    $buffer = '';
297
                    $fp = fopen($dir . $file, "r");
298
                    if ($fp) {
299
                        while (!feof($fp)) {
300
                            $buf = fgets($fp, 4096);
301
                            if (substr($buf, 0, 2) != '--') {
302
                                $buf = preg_replace('/--(.+)*/', '', $buf);
303
                                $buffer .= $buf;
304
                            }
305
                        }
306
                        fclose($fp);
307
308
                        $buffer = trim($buffer);
309
                        if ($conf->db->type == 'mysql' || $conf->db->type == 'mysqli') {    // For Mysql 5.5+, we must replace type=innodb with ENGINE=innodb
310
                            $buffer = preg_replace('/type=innodb/i', 'ENGINE=innodb', $buffer);
311
                        } else {
312
                            // Keyword ENGINE is MySQL-specific, so scrub it for
313
                            // other database types (mssql, pgsql)
314
                            $buffer = preg_replace('/type=innodb/i', '', $buffer);
315
                            $buffer = preg_replace('/ENGINE=innodb/i', '', $buffer);
316
                        }
317
318
                        // Replace the prefix tables
319
                        if ($conf->main_db_prefix != 'llx_') {
320
                            $buffer = preg_replace('/llx_/i', $conf->main_db_prefix, $buffer);
321
                        }
322
323
                        //print "<tr><td>Creation of table $name/td>";
324
                        $requestnb++;
325
326
                        dolibarr_install_syslog("step2: request: " . $buffer);
327
                        $resql = $db->query($buffer, 0, 'dml');
328
                        if ($resql) {
329
                            // print "<td>OK request ==== $buffer</td></tr>";
330
                            $db->free($resql);
331
                        } else {
332
                            if (
333
                                $db->errno() == 'DB_ERROR_TABLE_ALREADY_EXISTS' ||
334
                                $db->errno() == 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS'
335
                            ) {
336
                                //print "<td>already existing</td></tr>";
337
                            } else {
338
                                print "<tr><td>" . $this->langs->trans("CreateTableAndPrimaryKey", $name);
339
                                print "<br>\n" . $this->langs->trans("Request") . ' ' . $requestnb . ' : ' . $buffer . ' <br>Executed query : ' . $db->lastquery;
340
                                print "\n</td>";
341
                                print '<td><span class="error">' . $this->langs->trans("ErrorSQL") . " " . $db->errno() . " " . $db->error() . '</span></td></tr>';
342
                                $error++;
343
                            }
344
                        }
345
                    } else {
346
                        print "<tr><td>" . $this->langs->trans("CreateTableAndPrimaryKey", $name);
347
                        print "</td>";
348
                        print '<td><span class="error">' . $this->langs->trans("Error") . ' Failed to open file ' . $dir . $file . '</span></td></tr>';
349
                        $error++;
350
                        dolibarr_install_syslog("step2: failed to open file " . $dir . $file, LOG_ERR);
351
                    }
352
                }
353
354
                if ($tablefound) {
355
                    if ($error == 0) {
356
                        print '<tr><td>';
357
                        print $this->langs->trans("TablesAndPrimaryKeysCreation") . '</td><td><img src="../theme/eldy/img/ok.png" alt="Ok"></td></tr>';
358
                        $ok = 1;
359
                    }
360
                } else {
361
                    print '<tr><td>' . $this->langs->trans("ErrorFailedToFindSomeFiles", $dir) . '</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>';
362
                    dolibarr_install_syslog("step2: failed to find files to create database in directory " . $dir, LOG_ERR);
363
                }
364
            }
365
366
367
            /***************************************************************************************
368
             *
369
             * Load files tables/*.key.sql. Files with '-xxx' in name are excluded (they will be loaded during activation of module 'xxx').
370
             * To do after the files *.sql
371
             *
372
             ***************************************************************************************/
373
            if ($ok && $createkeys) {
374
                // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax)
375
                $dir = "mysql/tables/";
376
377
                $okkeys = 0;
378
                $handle = opendir($dir);
379
                dolibarr_install_syslog("step2: open keys directory " . $dir . " handle=" . $handle);
380
                $tablefound = 0;
381
                $tabledata = [];
382
                if (is_resource($handle)) {
383
                    while (($file = readdir($handle)) !== false) {
384
                        if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file) && preg_match('/\.key\.sql$/i', $file) && !preg_match('/\-/', $file)) {
385
                            $tablefound++;
386
                            $tabledata[] = $file;
387
                        }
388
                    }
389
                    closedir($handle);
390
                }
391
392
                // Sort list of sql files on alphabetical order (load order is important)
393
                sort($tabledata);
394
                foreach ($tabledata as $file) {
395
                    $name = substr($file, 0, dol_strlen($file) - 4);
396
                    //print "<tr><td>Creation of table $name</td>";
397
                    $buffer = '';
398
                    $fp = fopen($dir . $file, "r");
399
                    if ($fp) {
400
                        while (!feof($fp)) {
401
                            $buf = fgets($fp, 4096);
402
403
                            // Special case of lines allowed for some version only
404
                            // MySQL
405
                            if ($choix == 1 && preg_match('/^--\sV([0-9\.]+)/i', $buf, $reg)) {
406
                                $versioncommande = explode('.', $reg[1]);
407
                                //var_dump($versioncommande);
408
                                //var_dump($versionarray);
409
                                if (
410
                                    count($versioncommande) && count($versionarray)
411
                                    && versioncompare($versioncommande, $versionarray) <= 0
412
                                ) {
413
                                    // Version qualified, delete SQL comments
414
                                    $buf = preg_replace('/^--\sV([0-9\.]+)/i', '', $buf);
415
                                    //print "Ligne $i qualifiee par version: ".$buf.'<br>';
416
                                }
417
                            }
418
                            // PGSQL
419
                            if ($choix == 2 && preg_match('/^--\sPOSTGRESQL\sV([0-9\.]+)/i', $buf, $reg)) {
420
                                $versioncommande = explode('.', $reg[1]);
421
                                //var_dump($versioncommande);
422
                                //var_dump($versionarray);
423
                                if (
424
                                    count($versioncommande) && count($versionarray)
425
                                    && versioncompare($versioncommande, $versionarray) <= 0
426
                                ) {
427
                                    // Version qualified, delete SQL comments
428
                                    $buf = preg_replace('/^--\sPOSTGRESQL\sV([0-9\.]+)/i', '', $buf);
429
                                    //print "Ligne $i qualifiee par version: ".$buf.'<br>';
430
                                }
431
                            }
432
433
                            // Add line if no comment
434
                            if (!preg_match('/^--/i', $buf)) {
435
                                $buffer .= $buf;
436
                            }
437
                        }
438
                        fclose($fp);
439
440
                        // If several requests, we loop on each
441
                        $listesql = explode(';', $buffer);
442
                        foreach ($listesql as $req) {
443
                            $buffer = trim($req);
444
                            if ($buffer) {
445
                                // Replace the prefix tables
446
                                if ($conf->main_db_prefix != 'llx_') {
447
                                    $buffer = preg_replace('/llx_/i', $conf->main_db_prefix, $buffer);
448
                                }
449
450
                                //print "<tr><td>Creation of keys and table index $name: '$buffer'</td>";
451
                                $requestnb++;
452
453
                                dolibarr_install_syslog("step2: request: " . $buffer);
454
                                $resql = $db->query($buffer, 0, 'dml');
455
                                if ($resql) {
456
                                    //print "<td>OK request ==== $buffer</td></tr>";
457
                                    $db->free($resql);
458
                                } else {
459
                                    if (
460
                                        $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS' ||
461
                                        $db->errno() == 'DB_ERROR_CANNOT_CREATE' ||
462
                                        $db->errno() == 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS' ||
463
                                        $db->errno() == 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS' ||
464
                                        preg_match('/duplicate key name/i', $db->error())
465
                                    ) {
466
                                        //print "<td>Deja existante</td></tr>";
467
                                        $key_exists = 1;
468
                                    } else {
469
                                        print "<tr><td>" . $this->langs->trans("CreateOtherKeysForTable", $name);
470
                                        print "<br>\n" . $this->langs->trans("Request") . ' ' . $requestnb . ' : ' . $db->lastqueryerror();
471
                                        print "\n</td>";
472
                                        print '<td><span class="error">' . $this->langs->trans("ErrorSQL") . " " . $db->errno() . " " . $db->error() . '</span></td></tr>';
473
                                        $error++;
474
                                    }
475
                                }
476
                            }
477
                        }
478
                    } else {
479
                        print "<tr><td>" . $this->langs->trans("CreateOtherKeysForTable", $name);
480
                        print "</td>";
481
                        print '<td><span class="error">' . $this->langs->trans("Error") . " Failed to open file " . $dir . $file . "</span></td></tr>";
482
                        $error++;
483
                        dolibarr_install_syslog("step2: failed to open file " . $dir . $file, LOG_ERR);
484
                    }
485
                }
486
487
                if ($tablefound && $error == 0) {
488
                    print '<tr><td>';
489
                    print $this->langs->trans("OtherKeysCreation") . '</td><td><img src="../theme/eldy/img/ok.png" alt="Ok"></td></tr>';
490
                    $okkeys = 1;
491
                }
492
            }
493
494
495
            /***************************************************************************************
496
             *
497
             * Load the file 'functions.sql'
498
             *
499
             ***************************************************************************************/
500
            if ($ok && $createfunctions) {
501
                // For this file, we use a directory according to database type
502
                if ($choix == 1) {
503
                    $dir = "mysql/functions/";
504
                } elseif ($choix == 2) {
505
                    $dir = "pgsql/functions/";
506
                } elseif ($choix == 3) {
507
                    $dir = "mssql/functions/";
508
                } elseif ($choix == 4) {
509
                    $dir = "sqlite3/functions/";
510
                }
511
512
                // Creation of data
513
                $file = "functions.sql";
514
                if (file_exists($dir . $file)) {
515
                    $fp = fopen($dir . $file, "r");
516
                    dolibarr_install_syslog("step2: open function file " . $dir . $file . " handle=" . $fp);
517
                    if ($fp) {
518
                        $buffer = '';
519
                        while (!feof($fp)) {
520
                            $buf = fgets($fp, 4096);
521
                            if (substr($buf, 0, 2) != '--') {
522
                                $buffer .= $buf . "§";
523
                            }
524
                        }
525
                        fclose($fp);
526
                    }
527
                    //$buffer=preg_replace('/;\';/',";'§",$buffer);
528
529
                    // If several requests, we loop on each of them
530
                    $listesql = explode('§', $buffer);
531
                    foreach ($listesql as $buffer) {
532
                        $buffer = trim($buffer);
533
                        if ($buffer) {
534
                            // Replace the prefix in table names
535
                            if ($conf->main_db_prefix != 'llx_') {
536
                                $buffer = preg_replace('/llx_/i', $conf->main_db_prefix, $buffer);
537
                            }
538
                            dolibarr_install_syslog("step2: request: " . $buffer);
539
                            print "<!-- Insert line : " . $buffer . "<br>-->\n";
540
                            $resql = $db->query($buffer, 0, 'dml');
541
                            if ($resql) {
542
                                $ok = 1;
543
                                $db->free($resql);
544
                            } else {
545
                                if (
546
                                    $db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS'
547
                                    || $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
548
                                ) {
549
                                    //print "Insert line : ".$buffer."<br>\n";
550
                                } else {
551
                                    $ok = 0;
552
553
                                    print "<tr><td>" . $this->langs->trans("FunctionsCreation");
554
                                    print "<br>\n" . $this->langs->trans("Request") . ' ' . $requestnb . ' : ' . $buffer;
555
                                    print "\n</td>";
556
                                    print '<td><span class="error">' . $this->langs->trans("ErrorSQL") . " " . $db->errno() . " " . $db->error() . '</span></td></tr>';
557
                                    $error++;
558
                                }
559
                            }
560
                        }
561
                    }
562
563
                    print "<tr><td>" . $this->langs->trans("FunctionsCreation") . "</td>";
564
                    if ($ok) {
565
                        print '<td><img src="../theme/eldy/img/ok.png" alt="Ok"></td></tr>';
566
                    } else {
567
                        print '<td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>';
568
                        $ok = 1;
569
                    }
570
                }
571
            }
572
573
574
            /***************************************************************************************
575
             *
576
             * Load files data/*.sql. Files with '-xxx' in name are excluded (they will be loaded during activation of module 'xxx').
577
             *
578
             ***************************************************************************************/
579
            if ($ok && $createdata) {
580
                // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax)
581
                $dir = "mysql/data/";
582
583
                // Insert data
584
                $handle = opendir($dir);
585
                dolibarr_install_syslog("step2: open directory data " . $dir . " handle=" . $handle);
586
                $tablefound = 0;
587
                $tabledata = [];
588
                if (is_resource($handle)) {
589
                    while (($file = readdir($handle)) !== false) {
590
                        if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file) && !preg_match('/\-/', $file)) {
591
                            if (preg_match('/^llx_accounting_account_/', $file)) {
592
                                continue; // We discard data file of chart of account. This will be loaded when a chart is selected.
593
                            }
594
595
                            //print 'x'.$file.'-'.$createdata.'<br>';
596
                            if (is_numeric($createdata) || preg_match('/' . preg_quote($createdata) . '/i', $file)) {
597
                                $tablefound++;
598
                                $tabledata[] = $file;
599
                            }
600
                        }
601
                    }
602
                    closedir($handle);
603
                }
604
605
                // Sort list of data files on alphabetical order (load order is important)
606
                sort($tabledata);
607
                foreach ($tabledata as $file) {
608
                    $name = substr($file, 0, dol_strlen($file) - 4);
609
                    $fp = fopen($dir . $file, "r");
610
                    dolibarr_install_syslog("step2: open data file " . $dir . $file . " handle=" . $fp);
611
                    if ($fp) {
612
                        $arrayofrequests = [];
613
                        $linefound = 0;
614
                        $linegroup = 0;
615
                        $sizeofgroup = 1; // Grouping request to have 1 query for several requests does not works with mysql, so we use 1.
616
617
                        // Load all requests
618
                        while (!feof($fp)) {
619
                            $buffer = fgets($fp, 4096);
620
                            $buffer = trim($buffer);
621
                            if ($buffer) {
622
                                if (substr($buffer, 0, 2) == '--') {
623
                                    continue;
624
                                }
625
626
                                if ($linefound && ($linefound % $sizeofgroup) == 0) {
627
                                    $linegroup++;
628
                                }
629
                                if (empty($arrayofrequests[$linegroup])) {
630
                                    $arrayofrequests[$linegroup] = $buffer;
631
                                } else {
632
                                    $arrayofrequests[$linegroup] .= " " . $buffer;
633
                                }
634
635
                                $linefound++;
636
                            }
637
                        }
638
                        fclose($fp);
639
640
                        dolibarr_install_syslog("step2: found " . $linefound . " records, defined " . count($arrayofrequests) . " group(s).");
641
642
                        $okallfile = 1;
643
                        $db->begin();
644
645
                        // We loop on each requests of file
646
                        foreach ($arrayofrequests as $buffer) {
647
                            // Replace the tables prefixes
648
                            if ($conf->main_db_prefix != 'llx_') {
649
                                $buffer = preg_replace('/llx_/i', $conf->main_db_prefix, $buffer);
650
                            }
651
652
                            //dolibarr_install_syslog("step2: request: " . $buffer);
653
                            $resql = $db->query($buffer, 1);
654
                            if ($resql) {
655
                                //$db->free($resql);     // Not required as request we launch here does not return memory needs.
656
                            } else {
657
                                if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
658
                                    //print "<tr><td>Insertion ligne : $buffer</td><td>";
659
                                } else {
660
                                    $ok = 0;
661
                                    $okallfile = 0;
662
                                    print '<span class="error">' . $this->langs->trans("ErrorSQL") . " : " . $db->lasterrno() . " - " . $db->lastqueryerror() . " - " . $db->lasterror() . "</span><br>";
663
                                }
664
                            }
665
                        }
666
667
                        if ($okallfile) {
668
                            $db->commit();
669
                        } else {
670
                            $db->rollback();
671
                        }
672
                    }
673
                }
674
675
                print "<tr><td>" . $this->langs->trans("ReferenceDataLoading") . "</td>";
676
                if ($ok) {
677
                    print '<td><img src="../theme/eldy/img/ok.png" alt="Ok"></td></tr>';
678
                } else {
679
                    print '<td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>';
680
                    $ok = 1; // Data loading are not blocking errors
681
                }
682
            }
683
            print '</table>';
684
        } else {
685
            print 'Parameter action=set not defined';
686
        }
687
688
689
        $ret = 0;
690
        if (!$ok && isset($argv[1])) {
691
            $ret = 1;
692
        }
693
        dolibarr_install_syslog("Exit " . $ret);
694
695
        dolibarr_install_syslog("- step2: end");
696
697
// Force here a value we need after because master.inc.php is not loaded into step2.
698
// This code must be similar with the one into main.inc.php
699
700
        $this->conf->file->instance_unique_id = (empty($conf->main_instance_unique_id) ? (empty($dolibarr_main_cookie_cryptkey) ? '' : $dolibarr_main_cookie_cryptkey) : $conf->main_instance_unique_id); // Unique id of instance
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_cookie_cryptkey seems to never exist and therefore empty should always be true.
Loading history...
701
702
        $hash_unique_id = Security::dol_hash('dolibarr' . $this->conf->file->instance_unique_id, 'sha256');   // Note: if the global salt changes, this hash changes too so ping may be counted twice. We don't mind. It is for statistics purpose only.
0 ignored issues
show
Bug introduced by
The type DoliModules\Install\Controller\Security was not found. Did you mean Security? If so, make sure to prefix the type with \.
Loading history...
703
704
        $out = '<input type="checkbox" name="dolibarrpingno" id="dolibarrpingno"' . ((getDolGlobalString('MAIN_FIRST_PING_OK_ID') == 'disabled') ? '' : ' value="checked" checked="true"') . '> ';
705
        $out .= '<label for="dolibarrpingno">' . $this->langs->trans("MakeAnonymousPing") . '</label>';
706
707
        $out .= '<!-- Add js script to manage the uncheck of option to not send the ping -->';
708
        $out .= '<script type="text/javascript">';
709
        $out .= 'jQuery(document).ready(function(){';
710
        $out .= '  document.cookie = "DOLINSTALLNOPING_' . $hash_unique_id . '=0; path=/"' . "\n";
711
        $out .= '  jQuery("#dolibarrpingno").click(function() {';
712
        $out .= '    if (! $(this).is(\':checked\')) {';
713
        $out .= '      console.log("We uncheck anonymous ping");';
714
        $out .= '      document.cookie = "DOLINSTALLNOPING_' . $hash_unique_id . '=1; path=/"' . "\n";
715
        $out .= '    } else {' . "\n";
716
        $out .= '      console.log("We check anonymous ping");';
717
        $out .= '      document.cookie = "DOLINSTALLNOPING_' . $hash_unique_id . '=0; path=/"' . "\n";
718
        $out .= '    }' . "\n";
719
        $out .= '  });';
720
        $out .= '});';
721
        $out .= '</script>';
722
723
        print $out;
724
725
        return true;
726
    }
727
728
    /**
729
     * Allows to configure database access parameters.
730
     *
731
     * @return true
732
     */
733
    public function doStart(): bool
734
    {
735
        $this->langs->setDefaultLang('auto');
736
        $this->langs->loadLangs(['main', 'admin', 'install']);
737
738
        $this->template = 'install/start';
739
        $this->nextButton = true;
740
741
        /**
742
         * There may be a file called install.forced.php with predefined parameters for the
743
         * installation. In that case, these parameters cannot be modified. Used for guided
744
         * installations.
745
         *
746
         * At the moment, we prefer not to implement this option.
747
         *
748
         * The best place to implement it is when creating the conf.php file, because it is
749
         * not even necessary to install the program.
750
         */
751
752
        /*
753
        // Now we load forced values from install.forced.php file.
754
        $useforcedwizard = false;
755
        $forcedfile = "./install.forced.php";
756
        if ($conffile == "/etc/dolibarr/conf.php") {
757
            $forcedfile = "/etc/dolibarr/install.forced.php"; // Must be after inc.php
758
        }
759
        if (@file_exists($forcedfile)) {
760
            $useforcedwizard = true;
761
            include_once $forcedfile;
762
        }
763
        */
764
765
        dolibarr_install_syslog("- fileconf: entering fileconf.php page");
766
767
        /**
768
         * You can force preselected values of the config step of Dolibarr by adding a file
769
         * install.forced.php into directory htdocs/install (This is the case with some wizard
770
         * installer like DoliWamp, DoliMamp or DoliBuntu).
771
         * We first init "forced values" to nothing.
772
         *
773
         * $force_install_noedit empty if no block:
774
         *   1 = To block vars specific to distrib
775
         *   2 = To block all technical parameters
776
         */
777
778
        $this->force_install_noedit = '';
779
780
        $this->db_types = $this->getDbTypes();
781
782
        $this->refreshConfigFromPost();
783
784
        /**
785
         * If it is active it is 'on', if it is not active it is 'off'.
786
         * But if it's the first time, it will be 'null', and we use it as 'on'.
787
         */
788
        $this->force_install_mainforcehttps = ($_POST['main_force_https'] ?? 'on') === 'on';
789
        $this->install_createdatabase = ($_POST['db_create_database'] ?? 'off') === 'on';
790
        $this->force_install_createuser = ($_POST['db_create_user'] ?? 'off') === 'on';
791
792
        $this->db_user_root = getIfIsset('db_user_root', $this->db_user_root ?? '');
793
        $this->db_pass_root = getIfIsset('db_pass_root', $this->db_pass_root ?? '');
794
795
        session_start(); // To be able to keep info into session (used for not losing pass during navigation. pass must not transit through parameters)
796
797
        $this->subtitle = $this->langs->trans("ConfigurationFile");
798
799
        $this->nextButtonJs = 'return jscheckparam();';
800
801
        return true;
802
    }
803
804
    private function getDbTypes()
805
    {
806
        $drivers = PDO::getAvailableDrivers();
807
        foreach ($drivers as $driver) {
808
            switch ($driver) {
809
                case 'mysql':
810
                    $result[] = [
811
                        'shortname' => 'MySQL/MariaDB',
812
                        'classname' => $driver,
813
                        'min_version' => '',
814
                        'comment' => '',
815
                    ];
816
                    break;
817
                case 'pgsql':
818
                    $result[] = [
819
                        'shortname' => 'PostgreSQL',
820
                        'classname' => $driver,
821
                        'min_version' => '',
822
                        'comment' => '',
823
                    ];
824
                    break;
825
            }
826
        }
827
        return $result;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result seems to be defined by a foreach iteration on line 807. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
828
    }
829
830
    /**
831
     * Complete all configuration values, as received by POST.
832
     *
833
     * @return void
834
     */
835
    private function refreshConfigFromPost()
836
    {
837
        /**
838
         * config:
839
         *      "main"
840
         *          "base_path"
841
         *          "base_url"
842
         *          "data_path"
843
         *          "alt_base_path": array
844
         *          "alt_base_url": array:1
845
         *          "theme": "eldy"
846
         *      "db"
847
         *          "host"
848
         *          "port"
849
         *          "name"
850
         *          "user"
851
         *          "pass"
852
         *          "type"
853
         *          "prefix": "alx_"
854
         *          "charset": "utf8"
855
         *          "collation": "utf8_unicode_ci"
856
         *          "encryption": 0
857
         *          "cryptkey": ""
858
         */
859
860
        $this->config->main->base_path = getIfIsset('main_dir', $this->config->main->base_path);
861
        $this->config->main->data_path = getIfIsset('main_data_dir', $this->config->main->data_path);
862
        $this->config->main->base_url = getIfIsset('main_url', $this->config->main->base_url);
863
864
        $this->config->db->name = getIfIsset('db_name', $this->config->db->name);
865
        $this->config->db->type = getIfIsset('db_type', $this->config->db->type);
866
        $this->config->db->host = getIfIsset('db_host', $this->config->db->host);
867
        $this->config->db->port = getIfIsset('db_port', $this->config->db->port);
868
        $this->config->db->prefix = getIfIsset('db_prefix', $this->config->db->prefix);
869
870
        $this->config->db->user = getIfIsset('db_user', $this->config->db->user);
871
        $this->config->db->pass = getIfIsset('db_pass', $this->config->db->pass);
872
    }
873
874
    /**
875
     * Replaces automatic database login by actual value
876
     *
877
     * @param string $force_install_databaserootlogin Login
878
     *
879
     * @return string
880
     */
881
    function parse_database_login($force_install_databaserootlogin)
882
    {
883
        return preg_replace('/__SUPERUSERLOGIN__/', 'root', $force_install_databaserootlogin);
884
    }
885
886
    /**
887
     * Replaces automatic database password by actual value
888
     *
889
     * @param string $force_install_databaserootpass Password
890
     *
891
     * @return string
892
     */
893
    function parse_database_pass($force_install_databaserootpass)
894
    {
895
        return preg_replace('/__SUPERUSERPASSWORD__/', '', $force_install_databaserootpass);
896
    }
897
898
    /**
899
     * Automatically detect Dolibarr's main data root
900
     *
901
     * @param string $this ->dolibarr_main_document_root Current main document root
902
     *
903
     * @return string
904
     */
905
    function detect_dolibarr_main_data_root($dolibarr_main_document_root)
906
    {
907
        $dolibarr_main_data_root = preg_replace("/\/htdocs$/", "", $dolibarr_main_document_root);
908
        $dolibarr_main_data_root .= "/documents";
909
        return $dolibarr_main_data_root;
910
    }
911
912
    /**
913
     * Automatically detect Dolibarr's main URL root
914
     *
915
     * @return string
916
     */
917
    function detect_dolibarr_main_url_root()
918
    {
919
        // If defined (Ie: Apache with Linux)
920
        if (isset($_SERVER["SCRIPT_URI"])) {
921
            $dolibarr_main_url_root = $_SERVER["SCRIPT_URI"];
922
        } elseif (isset($_SERVER["SERVER_URL"]) && isset($_SERVER["DOCUMENT_URI"])) {
923
            // If defined (Ie: Apache with Caudium)
924
            $dolibarr_main_url_root = $_SERVER["SERVER_URL"] . $_SERVER["DOCUMENT_URI"];
925
        } else {
926
            // If SCRIPT_URI, SERVER_URL, DOCUMENT_URI not defined (Ie: Apache 2.0.44 for Windows)
927
            $proto = ((!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') || (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) ? 'https' : 'http';
928
            if (!empty($_SERVER["HTTP_HOST"])) {
929
                $serverport = $_SERVER["HTTP_HOST"];
930
            } elseif (!empty($_SERVER["SERVER_NAME"])) {
931
                $serverport = $_SERVER["SERVER_NAME"];
932
            } else {
933
                $serverport = 'localhost';
934
            }
935
            $dolibarr_main_url_root = $proto . "://" . $serverport . $_SERVER["SCRIPT_NAME"];
936
        }
937
        // Clean proposed URL
938
        // We assume /install to be under /htdocs, so we get the parent path of the current URL
939
        $dolibarr_main_url_root = dirname(dirname($dolibarr_main_url_root));
940
941
        return $dolibarr_main_url_root;
942
    }
943
944
    public function _body()
945
    {
946
        $this->selectLang = filter_input(INPUT_POST, 'selectlang');
947
        if (empty($this->selectLang)) {
948
            $this->selectLang = $this->lang->getDefaultLang();
949
        }
950
        $this->lang->setDefaultLang($this->selectLang);
951
        $this->lang->loadLangs(['main', 'admin', 'install', 'errors']);
952
953
        return parent::body();
0 ignored issues
show
Bug introduced by
The method body() does not exist on DoliCore\Base\DolibarrViewController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

953
        return parent::/** @scrutinizer ignore-call */ body();

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...
954
    }
955
956
    /**
957
     * Main installation/update screen that allows to select the language
958
     * if it was not previously selected.
959
     *
960
     * @return bool
961
     */
962
    public function doIndex(): bool
963
    {
964
        $this->langs->setDefaultLang('auto');
965
        $this->langs->loadLangs(['main', 'admin', 'install']);
966
967
        if (isset($this->config->main_url_root)) {
968
            return $this->doChecked();
969
        }
970
971
        $this->template = 'install/install';
972
        $this->nextButton = true;
973
974
        $form = new FormAdmin(null);
975
        $this->htmlComboLanguages = $form->select_language('auto', 'selectlang', 1, 0, 0, 1);
976
977
        return true;
978
    }
979
980
    /**
981
     * Perform a needs check for the application to determine if it meets all the
982
     * essential requirements.
983
     *
984
     * @return bool
985
     */
986
    public function doChecked(): bool
987
    {
988
        $this->selectLang = $_POST['selectlang'];
989
        $this->langs->setDefaultLang('auto');
990
        $this->langs->loadLangs(['main', 'admin', 'install']);
991
992
        $this->template = 'install/checked';
993
994
        $checks = Check::all();
995
996
        $value = $this->checkConfFile();
997
        if ($value['status'] !== Status::OK) {
998
            $checks[] = $value;
999
        }
1000
1001
        $conffile = Config::getDolibarrConfigFilename();
1002
        if (!file_exists($conffile)) {
1003
            $text = $this->langs->trans('YouMustCreateWithPermission', $conffile);
1004
            $text .= '<br><br>';
1005
            $text .= '<span class="opacitymedium">' . $this->langs->trans("CorrectProblemAndReloadPage", $_SERVER['PHP_SELF'] . '?testget=ok') . '</span>';
1006
1007
            $checks[] = [
1008
                'status' => Status::FAIL,
1009
                'text' => $text,
1010
            ];
1011
1012
            return static::setIcons($checks);
1013
        }
1014
1015
        $value = $this->checkIfWritable();
1016
        if ($value['status'] !== Status::OK) {
1017
            $checks[] = $value;
1018
1019
            return static::setIcons($checks);
1020
        }
1021
1022
        $value = $this->next();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $value is correct as $this->next() targeting DoliModules\Install\Cont...stallController::next() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1023
        return static::setIcons($checks);
1024
    }
1025
1026
    /**
1027
     * Ensures that the configuration file exists and can be read.
1028
     *
1029
     * @return array
1030
     */
1031
    private function checkConfFile(): array
1032
    {
1033
        $conffile = Config::getDolibarrConfigFilename();
1034
1035
        clearstatcache();
1036
        if (is_readable($conffile) && filesize($conffile) > 8) {
1037
            $this->syslog("check: conf file '" . $conffile . "' already defined");
1038
            return ['status' => Status::OK];
1039
        }
1040
1041
        // If not, we create it
1042
        $this->syslog("check: we try to create conf file '" . $conffile . "'");
1043
1044
        // First we try by copying example
1045
        if (@copy($conffile . ".example", $conffile)) {
1046
            // Success
1047
            $this->syslog("check: successfully copied file " . $conffile . ".example into " . $conffile);
1048
            return ['status' => Status::OK];
1049
        }
1050
1051
        // If failed, we try to create an empty file
1052
        $this->syslog("check: failed to copy file " . $conffile . ".example into " . $conffile . ". We try to create it.", LOG_WARNING);
1053
1054
        $fp = @fopen($conffile, "w");
1055
        if ($fp) {
1056
            @fwrite($fp, '<?php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fwrite(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1056
            /** @scrutinizer ignore-unhandled */ @fwrite($fp, '<?php');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1057
            @fwrite($fp, "\n");
1058
            if (fclose($fp)) {
1059
                return ['status' => Status::OK];
1060
            }
1061
        }
1062
1063
        $this->syslog("check: failed to create a new file " . $conffile . " into current dir " . getcwd() . ". Please check permissions.", LOG_ERR);
1064
        return [
1065
            'status' => Status::FAIL,
1066
            'text' => $this->langs->trans('ConfFileDoesNotExistsAndCouldNotBeCreated', 'conf.php')
1067
        ];
1068
    }
1069
1070
    private function setIcons(array $checks): bool
1071
    {
1072
        $ok = true;
1073
        $this->checks = [];
1074
        foreach ($checks as $check) {
1075
            if (!isset($check['text'])) {
1076
                continue;
1077
            }
1078
            $value = [];
1079
            $value['text'] = $check['text'];
1080
            switch ($check['status']) {
1081
                case Status::OK:
1082
                    $value['ok'] = true;
1083
                    $value['icon'] = 'tick';
1084
                    break;
1085
                case Status::WARNING:
1086
                    $value['ok'] = true;
1087
                    $value['icon'] = 'warning';
1088
                    break;
1089
                case Status::FAIL:
1090
                    $value['ok'] = false;
1091
                    $value['icon'] = 'error';
1092
                    $ok = false;
1093
            }
1094
            $this->checks[] = $value;
1095
        }
1096
1097
        if (!$ok) {
1098
            $this->checks[] = [
1099
                'ok' => false,
1100
                'icon' => 'error',
1101
                'text' => $this->langs->trans('ErrorGoBackAndCorrectParameters'),
1102
            ];
1103
        }
1104
1105
        return $ok;
1106
    }
1107
1108
    public function checkIfWritable()
1109
    {
1110
        $conffile = Config::getDolibarrConfigFilename();
1111
1112
        if (is_dir($conffile)) {
1113
            return [
1114
                'status' => Status::FAIL,
1115
                'text' => $this->langs->trans('ConfFileMustBeAFileNotADir', $conffile),
1116
            ];
1117
        }
1118
1119
        $this->allowInstall = is_writable($conffile);
1120
        if (!$this->allowInstall) {
1121
            return [
1122
                'status' => Status::FAIL,
1123
                'text' => $this->langs->trans('ConfFileIsNotWritable', $conffile),
1124
            ];
1125
        }
1126
1127
        return [
1128
            'status' => Status::OK,
1129
        ];
1130
    }
1131
1132
    public function next()
1133
    {
1134
        $configFilename = Config::getDolibarrConfigFilename();
1135
        $conf = Config::getConf();
1136
        $config = Config::getConfig($conf);
1137
1138
        $ok = false;
1139
        if (!empty($config->main_db_type) && !empty($config->main_document_root)) {
1140
            $this->errorBadMainDocumentRoot = '';
1141
            if ($config->main_document_root !== BASE_PATH) {
1142
                $this->errorBadMainDocumentRoot = "A $configFilename file exists with a dolibarr_main_document_root to $config->main_document_root that seems wrong. Try to fix or remove the $configFilename file.";
1143
                dol_syslog($this->errorBadMainDocumentRoot, LOG_WARNING);
1144
            } else {
1145
                // If password is encoded, we decode it
1146
                // TODO: Pending
1147
                if (preg_match('/crypted:/i', $config->main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_encrypted_pass seems to never exist and therefore empty should always be true.
Loading history...
1148
                    require_once $this->dolibarr_main_document_root . '/core/lib/security.lib.php';
0 ignored issues
show
Bug introduced by
The property dolibarr_main_document_root does not exist on DoliModules\Install\Controller\InstallController. Did you mean dolibarr_main_db_encryption?
Loading history...
1149
                    if (preg_match('/crypted:/i', $config->main_db_pass)) {
1150
                        $dolibarr_main_db_encrypted_pass = preg_replace('/crypted:/i', '', $config->main_db_pass); // We need to set this as it is used to know the password was initially encrypted
1151
                        $config->main_db_pass = dol_decode($dolibarr_main_db_encrypted_pass);
1152
                    } else {
1153
                        $config->main_db_pass = dol_decode($dolibarr_main_db_encrypted_pass);
1154
                    }
1155
                }
1156
1157
                // $conf already created in inc.php
1158
                $this->conf->db->type = $config->main_db_type;
1159
                $this->conf->db->host = $config->main_db_host;
1160
                $this->conf->db->port = $config->main_db_port;
1161
                $this->conf->db->name = $config->main_db_name;
1162
                $this->conf->db->user = $config->main_db_user;
1163
                $this->conf->db->pass = $config->main_db_pass;
1164
                $db = getDoliDBInstance($this->conf->db->type, $this->conf->db->host, $this->conf->db->user, $this->conf->db->pass, $this->conf->db->name, (int)$this->conf->db->port);
1165
                if ($db->connected && $db->database_selected) {
1166
                    $ok = true;
1167
                }
1168
            }
1169
        }
1170
1171
        $this->availableChoices = [];
1172
        $this->notAvailableChoices = [];
1173
1174
        // If database access is available, we set more variables
1175
        // TODO: Pending
1176
        if ($ok) {
1177
            if (empty($dolibarr_main_db_encryption)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_encryption seems to never exist and therefore empty should always be true.
Loading history...
1178
                $dolibarr_main_db_encryption = 0;
1179
            }
1180
            $this->conf->db->dolibarr_main_db_encryption = $dolibarr_main_db_encryption;
1181
            if (empty($dolibarr_main_db_cryptkey)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_cryptkey seems to never exist and therefore empty should always be true.
Loading history...
1182
                $dolibarr_main_db_cryptkey = '';
1183
            }
1184
            $this->conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey;
1185
1186
            $this->conf->setValues($db);
1187
            // Reset forced setup after the setValues
1188
            if (defined('SYSLOG_FILE')) {
1189
                $this->conf->global->SYSLOG_FILE = constant('SYSLOG_FILE');
1190
            }
1191
            $this->conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
1192
1193
            // Current version is $this->conf->global->MAIN_VERSION_LAST_UPGRADE
1194
            // Version to install is DOL_VERSION
1195
            $dolibarrlastupgradeversionarray = preg_split('/[\.-]/', isset($this->conf->global->MAIN_VERSION_LAST_UPGRADE) ? $this->conf->global->MAIN_VERSION_LAST_UPGRADE : (isset($this->conf->global->MAIN_VERSION_LAST_INSTALL) ? $this->conf->global->MAIN_VERSION_LAST_INSTALL : ''));
1196
            $dolibarrversiontoinstallarray = versiondolibarrarray();
1197
        }
1198
1199
        $this->printVersion = getDolGlobalString('MAIN_VERSION_LAST_UPGRADE') || getDolGlobalString('MAIN_VERSION_LAST_INSTALL');
1200
1201
        $foundrecommandedchoice = 0;
1202
1203
        if (empty($dolibarr_main_db_host)) {    // This means install process was not run
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_host does not exist. Did you maybe mean $dolibarr_main_db_cryptkey?
Loading history...
1204
            $foundrecommandedchoice = 1; // To show only once
1205
        }
1206
1207
        /*
1208
        $button = $this->allowInstall
1209
            ? '<input class="button" type="submit" name="action" value="' . $this->langs->trans("Start") . '">'
1210
            : ($foundrecommandedchoice ? '<span class="warning">' : '') . $this->langs->trans("InstallNotAllowed") . ($foundrecommandedchoice ? '</span>' : '');
1211
        */
1212
1213
        // TODO: We have to see how we can use the action, and that the text is displayed in the correct language
1214
        $button = $this->allowInstall
1215
            ? '<input class="button" type="submit" name="action" value="start">' . $this->langs->trans("Start")
1216
            : ($foundrecommandedchoice ? '<span class="warning">' : '') . $this->langs->trans("InstallNotAllowed") . ($foundrecommandedchoice ? '</span>' : '');
1217
1218
        // Show line of first install choice
1219
        $choice = [
1220
            'selected' => true,
1221
            'short' => $this->langs->trans("FreshInstall"),
1222
            'long' => $this->langs->trans("FreshInstallDesc"),
1223
            'active' => $this->allowInstall,
1224
            'button' => $button,
1225
        ];
1226
1227
        if (!isset($config->main_db_host) || empty($config->main_db_host)) {
1228
            $choice['long'] .= '<br><div class="center"><div class="ok suggestedchoice">' . $this->langs->trans("InstallChoiceSuggested") . '</div></div>';
1229
        }
1230
1231
        $this->availableChoices[] = $choice;
1232
1233
        $positionkey = ($foundrecommandedchoice ? 999 : 0);
1234
        if ($this->allowInstall) {
1235
            $available_choices[$positionkey] = $choice;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$available_choices was never initialized. Although not strictly required by PHP, it is generally a good practice to add $available_choices = array(); before regardless.
Loading history...
1236
        } else {
1237
            $notavailable_choices[$positionkey] = $choice;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$notavailable_choices was never initialized. Although not strictly required by PHP, it is generally a good practice to add $notavailable_choices = array(); before regardless.
Loading history...
1238
        }
1239
1240
        // Show upgrade lines
1241
        $allowupgrade = true;
1242
        if (empty($config->main_db_host)) {    // This means install process was not run
1243
            $allowupgrade = false;
1244
        }
1245
        if (getDolGlobalInt("MAIN_NOT_INSTALLED")) {
1246
            $allowupgrade = false;
1247
        }
1248
        if (GETPOST('allowupgrade')) {
1249
            $allowupgrade = true;
1250
        }
1251
1252
        $this->errorMigrations = false;
1253
        $migrationscript = $this->getMigrationScript();
1254
1255
        $count = 0;
1256
        foreach ($migrationscript as $migarray) {
1257
            $choice = '';
1258
1259
            $count++;
1260
            $recommended_choice = false;
1261
            $version = DOL_VERSION;
1262
            $versionfrom = $migarray['from'];
1263
            $versionto = $migarray['to'];
1264
            $versionarray = preg_split('/[\.-]/', $version);
1265
            $dolibarrversionfromarray = preg_split('/[\.-]/', $versionfrom);
1266
            $dolibarrversiontoarray = preg_split('/[\.-]/', $versionto);
1267
            // Define string newversionxxx that are used for text to show
1268
            $newversionfrom = preg_replace('/(\.[0-9]+)$/i', '.*', $versionfrom);
1269
            $newversionto = preg_replace('/(\.[0-9]+)$/i', '.*', $versionto);
1270
            $newversionfrombis = '';
1271
            if (versioncompare($dolibarrversiontoarray, $versionarray) < -2) {  // From x.y.z -> x.y.z+1
1272
                $newversionfrombis = ' ' . $this->langs->trans("or") . ' ' . $versionto;
1273
            }
1274
1275
            if ($ok) {
1276
                if (count($dolibarrlastupgradeversionarray) >= 2) { // If database access is available and last upgrade version is known
1277
                    // Now we check if this is the first qualified choice
1278
                    if (
1279
                        $allowupgrade && empty($foundrecommandedchoice) &&
1280
                        (versioncompare($dolibarrversiontoarray, $dolibarrlastupgradeversionarray) > 0 || versioncompare($dolibarrversiontoarray, $versionarray) < -2)
1281
                    ) {
1282
                        $foundrecommandedchoice = 1; // To show only once
1283
                        $recommended_choice = true;
1284
                    }
1285
                } else {
1286
                    // We cannot recommend a choice.
1287
                    // A version of install may be known, but we need last upgrade.
1288
                }
1289
            }
1290
1291
            $button = $this->langs->trans("NotAvailable");
1292
            if ($allowupgrade) {
1293
                $disabled = false;
1294
                if ($foundrecommandedchoice == 2) {
1295
                    $disabled = true;
1296
                }
1297
                if ($foundrecommandedchoice == 1) {
1298
                    $foundrecommandedchoice = 2;
1299
                }
1300
                if ($disabled) {
1301
                    $button = '<span class="opacitymedium">' . $this->langs->trans("NotYetAvailable") . '</span>';
1302
                } else {
1303
                    // TODO: Pending fix how to pass the version in an action
1304
                    $button = '<a class="button runupgrade" href="upgrade.php?action=upgrade' . ($count < count($migrationscript) ? '_' . $versionto : '') . '&selectlang=' . $this->selectLang . '&versionfrom=' . $versionfrom . '&versionto=' . $versionto . '">' . $this->langs->trans("Start") . '</a>';
1305
                }
1306
            }
1307
1308
            $choice = [
1309
                'selected' => $recommended_choice,
1310
                'short' => $this->langs->trans("Upgrade") . '<br>' . $newversionfrom . $newversionfrombis . ' -> ' . $newversionto,
1311
                'long' => $this->langs->trans("UpgradeDesc"),
1312
                'active' => $this->allowInstall,
1313
                'button' => $button,
1314
            ];
1315
1316
            if ($recommended_choice) {
1317
                $choice['long'] .= '<br><div class="center"><div class="ok suggestedchoice">' . $this->langs->trans("InstallChoiceSuggested") . '</div>';
1318
                if ($count < count($migarray)) {
1319
                    $choice['long'] .= $this->langs->trans('MigrateIsDoneStepByStep', DOL_VERSION);
1320
                }
1321
                $choice['long'] .= '</div>';
1322
            }
1323
1324
            if ($allowupgrade) {
1325
                $this->availableChoices[$count] = $choice;
1326
            } else {
1327
                $this->notAvailableChoices[$count] = $choice;
1328
            }
1329
        }
1330
1331
        // If there is no choice at all, we show all of them.
1332
        if (empty($this->availableChoices)) {
1333
            $this->availableChoices = $this->notAvailableChoices;
1334
            $this->notAvailableChoices = [];
1335
        }
1336
1337
        // Array of install choices
1338
        krsort($this->availableChoices, SORT_NATURAL);
1339
    }
1340
1341
    private function getMigrationScript()
1342
    {
1343
        $dir = BASE_PATH . "/../Dolibarr/Modules/Install/mysql/migration/";   // We use mysql migration scripts whatever is database driver
1344
        dolibarr_install_syslog("Scan sql files for migration files in " . $dir);
1345
1346
        // Get files list of migration file x.y.z-a.b.c.sql into /install/mysql/migration
1347
        $migrationscript = [];
1348
        $handle = opendir($dir);
1349
        if (!is_resource($handle)) {
1350
            $this->errorMigrations = $this->langs->trans("ErrorCanNotReadDir", $dir);
0 ignored issues
show
Documentation Bug introduced by
The property $errorMigrations was declared of type false, but $this->langs->trans('ErrorCanNotReadDir', $dir) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1351
            return [];
1352
        }
1353
1354
        $versiontousetoqualifyscript = preg_replace('/-.*/', '', DOL_VERSION);
1355
        while (($file = readdir($handle)) !== false) {
1356
            $reg = [];
1357
            if (preg_match('/^(\d+\.\d+\.\d+)-(\d+\.\d+\.\d+)\.sql$/i', $file, $reg)) {
1358
                //var_dump(DOL_VERSION." ".$reg[2]." ".$versiontousetoqualifyscript." ".version_compare($versiontousetoqualifyscript, $reg[2]));
1359
                if (!empty($reg[2]) && version_compare($versiontousetoqualifyscript, $reg[2]) >= 0) {
1360
                    $migrationscript[] = ['from' => $reg[1], 'to' => $reg[2]];
1361
                }
1362
            }
1363
        }
1364
        return dol_sort_array($migrationscript, 'from', 'asc', 1);
1365
    }
1366
1367
    public function doConfig(): bool
1368
    {
1369
        $this->langs->setDefaultLang('auto');
1370
        $this->langs->loadLangs(['main', 'admin', 'install', 'errors']);
1371
1372
        /**
1373
         * "main_dir"
1374
         * "main_data_dir"
1375
         * "main_url"
1376
         * "db_name"
1377
         * "db_type"
1378
         * "db_host"
1379
         * "db_port"
1380
         * "db_prefix"
1381
         * "db_user"
1382
         * "db_pass"
1383
         * "db_create_user"
1384
         * "db_create_database"
1385
         *      "db_user_root"
1386
         *      "db_pass_root"
1387
         */
1388
1389
        $this->template = 'install/step1';
1390
        $this->nextButton = true;
1391
1392
        $oldConf = $this->config;
1393
        $this->refreshConfigFromPost();
1394
1395
        $this->dolibarr_main_distrib = 'standard';
1396
1397
        session_start(); // To be able to keep info into session (used for not losing password during navigation. The password must not transit through parameters)
1398
1399
        // Save a flag to tell to restore input value if we go back
1400
        $_SESSION['dol_save_pass'] = $this->db_pass;
0 ignored issues
show
Bug introduced by
The property db_pass does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_pass_root?
Loading history...
1401
        //$_SESSION['dol_save_passroot']=$passroot;
1402
1403
        $conffile = Config::getDolibarrConfigFilename();
1404
1405
        /*
1406
        // Now we load forced values from install.forced.php file.
1407
        $useforcedwizard = false;
1408
        $forcedfile = "./install.forced.php";
1409
        if ($conffile == "/etc/dolibarr/conf.php") {
1410
            $forcedfile = "/etc/dolibarr/install.forced.php";
1411
        }
1412
        if (@file_exists($forcedfile)) {
1413
            $useforcedwizard = true;
1414
            include_once $forcedfile;
1415
            // If forced install is enabled, replace the post values. These are empty because form fields are disabled.
1416
            if ($force_install_noedit) {
1417
                $this->main_dir = detect_dolibarr_main_document_root();
1418
                if (!empty($argv[3])) {
1419
                    $this->main_dir = $argv[3]; // override when executing the script in command line
1420
                }
1421
                if (!empty($force_install_main_data_root)) {
1422
                    $this->main_data_dir = $force_install_main_data_root;
1423
                } else {
1424
                    $this->main_data_dir = detect_dolibarr_main_data_root($this->main_dir);
1425
                }
1426
                if (!empty($argv[4])) {
1427
                    $this->main_data_dir = $argv[4]; // override when executing the script in command line
1428
                }
1429
                $this->main_url = detect_dolibarr_main_url_root();
1430
                if (!empty($argv[5])) {
1431
                    $this->main_url = $argv[5]; // override when executing the script in command line
1432
                }
1433
1434
                if (!empty($force_install_databaserootlogin)) {
1435
                    $userroot = parse_database_login($force_install_databaserootlogin);
1436
                }
1437
                if (!empty($argv[6])) {
1438
                    $userroot = $argv[6]; // override when executing the script in command line
1439
                }
1440
                if (!empty($force_install_databaserootpass)) {
1441
                    $passroot = parse_database_pass($force_install_databaserootpass);
1442
                }
1443
                if (!empty($argv[7])) {
1444
                    $passroot = $argv[7]; // override when executing the script in command line
1445
                }
1446
            }
1447
            if ($force_install_noedit == 2) {
1448
                if (!empty($force_install_type)) {
1449
                    $this->db_type = $force_install_type;
1450
                }
1451
                if (!empty($force_install_dbserver)) {
1452
                    $this->db_host = $force_install_dbserver;
1453
                }
1454
                if (!empty($force_install_database)) {
1455
                    $this->db_name = $force_install_database;
1456
                }
1457
                if (!empty($force_install_databaselogin)) {
1458
                    $this->db_user = $force_install_databaselogin;
1459
                }
1460
                if (!empty($force_install_databasepass)) {
1461
                    $this->db_pass = $force_install_databasepass;
1462
                }
1463
                if (!empty($force_install_port)) {
1464
                    $this->db_port = $force_install_port;
1465
                }
1466
                if (!empty($force_install_prefix)) {
1467
                    $this->db_prefix = $force_install_prefix;
1468
                }
1469
                if (!empty($force_install_createdatabase)) {
1470
                    $this->db_create_database = $force_install_createdatabase;
1471
                }
1472
                if (!empty($force_install_createuser)) {
1473
                    $this->db_create_user = $force_install_createuser;
1474
                }
1475
                if (!empty($force_install_mainforcehttps)) {
1476
                    $this->main_force_https = $force_install_mainforcehttps;
1477
                }
1478
            }
1479
1480
            if (!empty($force_install_distrib)) {
1481
                $this->dolibarr_main_distrib = $force_install_distrib;
1482
            }
1483
        }
1484
        */
1485
1486
        dolibarr_install_syslog("--- step1: entering step1.php page");
1487
1488
        // Test if we can run a first install process
1489
        if (!is_writable($conffile)) {
1490
            $this->template = 'install/step1-error';
1491
            $this->errorMessage = $this->langs->trans("ConfFileIsNotWritable", $conffile);
1492
            return false;
1493
        }
1494
1495
        $errors = [];
1496
1497
        // Check parameters
1498
        $is_sqlite = false;
1499
1500
        if (empty($this->db_type)) {
0 ignored issues
show
Bug introduced by
The property db_type does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_types?
Loading history...
1501
            $errors[] = $this->langs->trans("ErrorFieldRequired", $this->langs->transnoentities("DatabaseType"));
1502
        } else {
1503
            $is_sqlite = ($this->db_type === 'sqlite' || $this->db_type === 'sqlite3');
1504
        }
1505
1506
        if (empty($this->db_host) && !$is_sqlite) {
1507
            $errors[] = $this->langs->trans("ErrorFieldRequired", $this->langs->transnoentities("Server"));
1508
        }
1509
1510
        if (empty($this->db_name)) {
1511
            $errors[] = $this->langs->trans("ErrorFieldRequired", $this->langs->transnoentities("DatabaseName"));
1512
        }
1513
1514
        if (empty($this->db_user) && !$is_sqlite) {
0 ignored issues
show
Bug introduced by
The property db_user does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_user_root?
Loading history...
1515
            $errors[] = $this->langs->trans("ErrorFieldRequired", $this->langs->transnoentities("Login"));
1516
        }
1517
1518
        if (!empty($this->db_port) && !is_numeric($this->db_port)) {
0 ignored issues
show
Bug Best Practice introduced by
The property db_port does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
1519
            $errors[] = $this->langs->trans("ErrorBadValueForParameter", $this->db_port, $this->langs->transnoentities("Port"));
1520
        }
1521
1522
        if (!empty($this->db_prefix) && !preg_match('/^[a-z0-9]+_$/i', $this->db_prefix)) {
0 ignored issues
show
Bug introduced by
The property db_prefix does not exist on DoliModules\Install\Controller\InstallController. Did you mean prefix?
Loading history...
1523
            $errors[] = $this->langs->trans("ErrorBadValueForParameter", $this->db_prefix, $this->langs->transnoentities("DatabasePrefix"));
1524
        }
1525
1526
        $this->main_dir = dol_sanitizePathName($this->main_dir);
1527
        $this->main_data_dir = dol_sanitizePathName($this->main_data_dir);
1528
1529
        if (!filter_var($this->main_url, FILTER_VALIDATE_URL)) {
1530
            $errors[] = $this->langs->trans("ErrorBadValueForParameter", $this->main_url, $this->langs->transnoentitiesnoconv("URLRoot"));
1531
        }
1532
1533
        // Remove last / into dans main_dir
1534
        if (substr($this->main_dir, dol_strlen($this->main_dir) - 1) == "/") {
1535
            $this->main_dir = substr($this->main_dir, 0, dol_strlen($this->main_dir) - 1);
1536
        }
1537
1538
        // Remove last / into dans main_url
1539
        if (!empty($this->main_url) && substr($this->main_url, dol_strlen($this->main_url) - 1) == "/") {
1540
            $this->main_url = substr($this->main_url, 0, dol_strlen($this->main_url) - 1);
1541
        }
1542
1543
        $enginesDir = realpath(BASE_PATH . '/../Core/DB/Engines') . '/';
1544
        if (!Files::dol_is_dir($enginesDir)) {
1545
            $errors[] = $this->langs->trans("ErrorBadValueForParameter", $this->main_dir, $this->langs->transnoentitiesnoconv("WebPagesDirectory"));
1546
        }
1547
1548
        $this->errors = $errors;
1549
        $error = count($errors) > 0;
1550
1551
        // Test database connection
1552
        if (!$error) {
1553
            $result = @include_once $enginesDir . $this->db_type . '.php';
1554
1555
            if ($result) {
1556
                // If we require database or user creation we need to connect as root, so we need root login credentials
1557
                if (!empty($this->db_create_database) && !$userroot) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $userroot seems to be never defined.
Loading history...
1558
                    print '
1559
        <div class="error">' . $this->langs->trans("YouAskDatabaseCreationSoDolibarrNeedToConnect", $this->db_name) . '</div>
0 ignored issues
show
Bug Best Practice introduced by
The property db_name does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
1560
        ';
1561
                    print '<br>';
1562
                    print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1563
                    print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1564
                    $error++;
1565
                }
1566
                if (!empty($this->db_create_user) && !$userroot) {
1567
                    print '
1568
        <div class="error">' . $this->langs->trans("YouAskLoginCreationSoDolibarrNeedToConnect", $this->db_user) . '</div>
1569
        ';
1570
                    print '<br>';
1571
                    print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1572
                    print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1573
                    $error++;
1574
                }
1575
1576
                // If we need root access
1577
                if (!$error && (!empty($this->db_create_database) || !empty($this->db_create_user))) {
1578
                    $databasefortest = $this->db_name;
1579
                    if (!empty($this->db_create_database)) {
1580
                        if ($this->db_type == 'mysql' || $this->db_type == 'mysqli') {
1581
                            $databasefortest = 'mysql';
1582
                        } elseif ($this->db_type == 'pgsql') {
1583
                            $databasefortest = 'postgres';
1584
                        } else {
1585
                            $databasefortest = 'master';
1586
                        }
1587
                    }
1588
1589
                    $db = getDoliDBInstance($this->db_type, $this->db_host, $userroot, $passroot, $databasefortest, (int)$this->db_port);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $passroot seems to be never defined.
Loading history...
Bug Best Practice introduced by
The property db_host does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
1590
1591
                    dol_syslog("databasefortest=" . $databasefortest . " connected=" . $db->connected . " database_selected=" . $db->database_selected, LOG_DEBUG);
1592
                    //print "databasefortest=".$databasefortest." connected=".$db->connected." database_selected=".$db->database_selected;
1593
1594
                    if (empty($this->db_create_database) && $db->connected && !$db->database_selected) {
1595
                        print '
1596
        <div class="error">' . $this->langs->trans("ErrorConnectedButDatabaseNotFound", $this->db_name) . '</div>
1597
        ';
1598
                        print '<br>';
1599
                        if (!$db->connected) {
1600
                            print $this->langs->trans("IfDatabaseNotExistsGoBackAndUncheckCreate") . '<br><br>';
1601
                        }
1602
                        print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1603
                        $error++;
1604
                    } elseif ($db->error && !(!empty($this->db_create_database) && $db->connected)) {
1605
                        // Note: you may experience error here with message "No such file or directory" when mysql was installed for the first time but not yet launched.
1606
                        if ($db->error == "No such file or directory") {
1607
                            print '
1608
        <div class="error">' . $this->langs->trans("ErrorToConnectToMysqlCheckInstance") . '</div>
1609
        ';
1610
                        } else {
1611
                            print '
1612
        <div class="error">' . $db->error . '</div>
1613
        ';
1614
                        }
1615
                        if (!$db->connected) {
1616
                            print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1617
                        }
1618
                        //print '<a href="#" onClick="javascript: history.back();">';
1619
                        print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1620
                        //print '</a>';
1621
                        $error++;
1622
                    }
1623
                }
1624
1625
                // If we need simple access
1626
                if (!$error && (empty($this->db_create_database) && empty($this->db_create_user))) {
1627
                    $db = getDoliDBInstance($this->db_type, $this->db_host, $this->db_user, $this->db_pass, $this->db_name, (int)$this->db_port);
1628
1629
                    if ($db->error) {
1630
                        print '
1631
        <div class="error">' . $db->error . '</div>
1632
        ';
1633
                        if (!$db->connected) {
1634
                            print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1635
                        }
1636
                        //print '<a href="#" onClick="javascript: history.back();">';
1637
                        print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1638
                        //print '</a>';
1639
                        $error++;
1640
                    }
1641
                }
1642
            } else {
1643
                print "<br>\nFailed to include_once(\"" . $enginesDir . $this->db_type . ".class.php\")<br>\n";
1644
                print '
1645
        <div class="error">' . $this->langs->trans(
1646
                        "ErrorWrongValueForParameter",
1647
                        $this->langs->transnoentities("WebPagesDirectory")) . '
1648
        </div>
1649
        ';
1650
                //print '<a href="#" onClick="javascript: history.back();">';
1651
                print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1652
                //print '</a>';
1653
                $error++;
1654
            }
1655
        } else {
1656
            if (isset($db)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to never exist and therefore isset should always be false.
Loading history...
1657
                print $db->lasterror();
1658
            }
1659
            if (isset($db) && !$db->connected) {
1660
                print '<br>' . $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1661
            }
1662
            print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1663
            $error++;
1664
        }
1665
1666
        if (!$error && $db->connected) {
1667
            if (!empty($this->db_create_database)) {
1668
                $result = $db->select_db($this->db_name);
1669
                if ($result) {
1670
                    print '<div class="error">' . $this->langs->trans("ErrorDatabaseAlreadyExists", $this->db_name) . '</div>';
1671
                    print $this->langs->trans("IfDatabaseExistsGoBackAndCheckCreate") . '<br><br>';
1672
                    print $this->langs->trans("ErrorGoBackAndCorrectParameters");
1673
                    $error++;
1674
                }
1675
            }
1676
        }
1677
1678
// Define $defaultCharacterSet and $defaultDBSortingCollation
1679
        if (!$error && $db->connected) {
1680
            if (!empty($this->db_create_database)) {    // If we create database, we force default value
1681
                // Default values come from the database handler
1682
1683
                $defaultCharacterSet = $db->forcecharset;
1684
                $defaultDBSortingCollation = $db->forcecollate;
1685
            } else { // If already created, we take current value
1686
                $defaultCharacterSet = $db->getDefaultCharacterSetDatabase();
1687
                $defaultDBSortingCollation = $db->getDefaultCollationDatabase();
1688
            }
1689
1690
            // It seems some PHP driver mysqli does not support utf8mb3
1691
            if ($defaultCharacterSet == 'utf8mb3' || $defaultDBSortingCollation == 'utf8mb3_unicode_ci') {
1692
                $defaultCharacterSet = 'utf8';
1693
                $defaultDBSortingCollation = 'utf8_unicode_ci';
1694
            }
1695
            // Force to avoid utf8mb4 because index on field char 255 reach limit of 767 char for indexes (example with mysql 5.6.34 = mariadb 10.0.29)
1696
            // TODO Remove this when utf8mb4 is supported
1697
            if ($defaultCharacterSet == 'utf8mb4' || $defaultDBSortingCollation == 'utf8mb4_unicode_ci') {
1698
                $defaultCharacterSet = 'utf8';
1699
                $defaultDBSortingCollation = 'utf8_unicode_ci';
1700
            }
1701
1702
            print '<input type="hidden" name="dolibarr_main_db_character_set" value="' . $defaultCharacterSet . '">';
1703
            print '<input type="hidden" name="dolibarr_main_db_collation" value="' . $defaultDBSortingCollation . '">';
1704
            $this->db_character_set = $defaultCharacterSet;
1705
            $this->db_collation = $defaultDBSortingCollation;
1706
            dolibarr_install_syslog("step1: db_character_set=" . $this->db_character_set . " db_collation=" . $this->db_collation);
1707
        }
1708
1709
// Create config file
1710
        if (!$error && $db->connected) {
1711
            umask(0);
1712
            if (is_array($_POST)) {
1713
                foreach ($_POST as $key => $value) {
1714
                    if (!preg_match('/^db_pass/i', $key)) {
1715
                        dolibarr_install_syslog("step1: choice for " . $key . " = " . $value);
1716
                    }
1717
                }
1718
            }
1719
1720
            // Show title of step
1721
            print '<h3><img class="valignmiddle inline-block paddingright" src="' . $this->config->file->main_url . '/' . $this->config->main->theme . '/img/gear.svg" width="20" alt="Configuration"> ' . $this->langs->trans("ConfigurationFile") . '</h3>';
1722
            print '<table cellspacing="0" width="100%" cellpadding="1" border="0">';
1723
1724
            // Check parameter main_dir
1725
            if (!$error) {
1726
                if (!is_dir($this->main_dir)) {
1727
                    dolibarr_install_syslog("step1: directory '" . $this->main_dir . "' is unavailable or can't be accessed");
1728
1729
                    print "<tr><td>";
1730
                    print $this->langs->trans("ErrorDirDoesNotExists", $this->main_dir) . '<br>';
1731
                    print $this->langs->trans("ErrorWrongValueForParameter", $this->langs->transnoentitiesnoconv("WebPagesDirectory")) . '<br>';
1732
                    print $this->langs->trans("ErrorGoBackAndCorrectParameters") . '<br><br>';
1733
                    print '</td><td>';
1734
                    print $this->langs->trans("Error");
1735
                    print "</td></tr>";
1736
                    $error++;
1737
                }
1738
            }
1739
1740
            if (!$error) {
1741
                dolibarr_install_syslog("step1: directory '" . $this->main_dir . "' exists");
1742
            }
1743
1744
1745
            // Create subdirectory main_data_dir
1746
            if (!$error) {
1747
                // Create directory for documents
1748
                if (!is_dir($this->main_data_dir)) {
1749
                    dol_mkdir($this->main_data_dir);
1750
                }
1751
1752
                if (!is_dir($this->main_data_dir)) {
1753
                    print "<tr><td>" . $this->langs->trans("ErrorDirDoesNotExists", $this->main_data_dir);
1754
                    print ' ' . $this->langs->trans("YouMustCreateItAndAllowServerToWrite");
1755
                    print '</td><td>';
1756
                    print '<span class="error">' . $this->langs->trans("Error") . '</span>';
1757
                    print "</td></tr>";
1758
                    print '<tr><td colspan="2"><br>' . $this->langs->trans("CorrectProblemAndReloadPage", $_SERVER['PHP_SELF'] . '?testget=ok') . '</td></tr>';
1759
                    $error++;
1760
                } else {
1761
                    // Create .htaccess file in document directory
1762
                    $pathhtaccess = $this->main_data_dir . '/.htaccess';
1763
                    if (!file_exists($pathhtaccess)) {
1764
                        dolibarr_install_syslog("step1: .htaccess file did not exist, we created it in '" . $this->main_data_dir . "'");
1765
                        $handlehtaccess = @fopen($pathhtaccess, 'w');
1766
                        if ($handlehtaccess) {
1767
                            fwrite($handlehtaccess, 'Order allow,deny' . "\n");
1768
                            fwrite($handlehtaccess, 'Deny from all' . "\n");
1769
1770
                            fclose($handlehtaccess);
1771
                            dolibarr_install_syslog("step1: .htaccess file created");
1772
                        }
1773
                    }
1774
1775
                    // Documents are stored above the web pages root to prevent being downloaded without authentication
1776
                    $dir = [];
1777
                    $dir[] = $this->main_data_dir . "/mycompany";
1778
                    $dir[] = $this->main_data_dir . "/medias";
1779
                    $dir[] = $this->main_data_dir . "/users";
1780
                    $dir[] = $this->main_data_dir . "/facture";
1781
                    $dir[] = $this->main_data_dir . "/propale";
1782
                    $dir[] = $this->main_data_dir . "/ficheinter";
1783
                    $dir[] = $this->main_data_dir . "/produit";
1784
                    $dir[] = $this->main_data_dir . "/doctemplates";
1785
1786
                    // Loop on each directory of dir [] to create them if they do not exist
1787
                    $num = count($dir);
1788
                    for ($i = 0; $i < $num; $i++) {
1789
                        if (is_dir($dir[$i])) {
1790
                            dolibarr_install_syslog("step1: directory '" . $dir[$i] . "' exists");
1791
                        } else {
1792
                            if (dol_mkdir($dir[$i]) < 0) {
1793
                                $this->errors[] = $this->langs->trans('ErrorFailToCreateDir', $dir[$i]);
1794
                            } else {
1795
                                dolibarr_install_syslog("step1: directory '" . $dir[$i] . "' created");
1796
                            }
1797
                        }
1798
                    }
1799
1800
                    // Copy directory medias
1801
                    $srcroot = $this->main_dir . '/install/medias';
1802
                    $destroot = $this->main_data_dir . '/medias';
1803
                    Files::dolCopyDir($srcroot, $destroot, 0, 0);
1804
1805
                    if ($error) {
1806
                        print "<tr><td>" . $this->langs->trans("ErrorDirDoesNotExists", $this->main_data_dir);
1807
                        print ' ' . $this->langs->trans("YouMustCreateItAndAllowServerToWrite");
1808
                        print '</td><td>';
1809
                        print '<span class="error">' . $this->langs->trans("Error") . '</span>';
1810
                        print "</td></tr>";
1811
                        print '<tr><td colspan="2"><br>' . $this->langs->trans("CorrectProblemAndReloadPage", $_SERVER['PHP_SELF'] . '?testget=ok') . '</td></tr>';
1812
                    } else {
1813
                        //ODT templates
1814
                        $srcroot = $this->main_dir . '/Install/DocTemplates';
1815
                        $destroot = $this->main_data_dir . '/doctemplates';
1816
                        $docs = [
1817
                            'contracts' => 'contract',
1818
                            'invoices' => 'invoice',
1819
                            'orders' => 'order',
1820
                            'products' => 'product',
1821
                            'projects' => 'project',
1822
                            'proposals' => 'proposal',
1823
                            'shipments' => 'shipment',
1824
                            'supplier_proposals' => 'supplier_proposal',
1825
                            'tasks' => 'task_summary',
1826
                            'thirdparties' => 'thirdparty',
1827
                            'usergroups' => 'usergroups',
1828
                            'users' => 'user',
1829
                        ];
1830
                        foreach ($docs as $cursordir => $cursorfile) {
1831
                            $src = $srcroot . '/' . $cursordir . '/template_' . $cursorfile . '.odt';
1832
                            $dirodt = $destroot . '/' . $cursordir;
1833
                            $dest = $dirodt . '/template_' . $cursorfile . '.odt';
1834
1835
                            dol_mkdir($dirodt);
1836
                            $result = Files::dol_copy($src, $dest, 0, 0);
1837
                            if ($result < 0) {
1838
                                $this->errors[] = $this->langs->trans('ErrorFailToCopyFile', $src, $dest);
1839
                            }
1840
                        }
1841
                    }
1842
                }
1843
            }
1844
1845
            // Table prefix
1846
            $this->main_db_prefix = (!empty($this->db_prefix) ? $this->db_prefix : 'llx_');
1847
1848
            // Write conf file on disk
1849
            if (!$error) {
1850
                // Save old conf file on disk
1851
                if (file_exists("$conffile")) {
1852
                    // We must ignore errors as an existing old file may already exist and not be replaceable or
1853
                    // the installer (like for ubuntu) may not have permission to create another file than conf.php.
1854
                    // Also no other process must be able to read file or we expose the new file, so content with password.
1855
                    @Files::dol_copy($conffile, $conffile . '.old', '0400');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for dol_copy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1855
                    /** @scrutinizer ignore-unhandled */ @Files::dol_copy($conffile, $conffile . '.old', '0400');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1856
                }
1857
1858
                $error += $this->write_conf_file($conffile);
1859
            }
1860
1861
            // Create database and admin user database
1862
            if (!$error) {
1863
                // We reload configuration file
1864
                $this->conf();
1865
1866
                print '<tr><td>';
1867
                print $this->langs->trans("ConfFileReload");
1868
                print '</td>';
1869
                print '<td><img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/ok.png" alt="Ok"></td></tr>';
1870
1871
                // Create database user if requested
1872
                if (isset($this->db_create_user) && ($this->db_create_user == "1" || $this->db_create_user == "on")) {
1873
                    dolibarr_install_syslog("step1: create database user: " . $dolibarr_main_db_user);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_user seems to be never defined.
Loading history...
1874
1875
                    //print $this->conf->db->host." , ".$this->conf->db->name." , ".$this->conf->db->user." , ".$this->conf->db->port;
1876
                    $databasefortest = $this->conf->db->name;
1877
                    if ($this->conf->db->type == 'mysql' || $this->conf->db->type == 'mysqli') {
1878
                        $databasefortest = 'mysql';
1879
                    } elseif ($this->conf->db->type == 'pgsql') {
1880
                        $databasefortest = 'postgres';
1881
                    } elseif ($this->conf->db->type == 'mssql') {
1882
                        $databasefortest = 'master';
1883
                    }
1884
1885
                    // Check database connection
1886
1887
                    $db = getDoliDBInstance($this->conf->db->type, $this->conf->db->host, $userroot, $passroot, $databasefortest, (int)$this->conf->db->port);
1888
1889
                    if ($db->error) {
1890
                        print '<div class="error">' . $db->error . '</div>';
1891
                        $error++;
1892
                    }
1893
1894
                    if (!$error) {
1895
                        if ($db->connected) {
1896
                            $resultbis = 1;
1897
1898
                            if (empty($dolibarr_main_db_pass)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_pass seems to never exist and therefore empty should always be true.
Loading history...
1899
                                dolibarr_install_syslog("step1: failed to create user, password is empty", LOG_ERR);
1900
                                print '<tr><td>';
1901
                                print $this->langs->trans("UserCreation") . ' : ';
1902
                                print $dolibarr_main_db_user;
1903
                                print '</td>';
1904
                                print '<td>' . $this->langs->trans("Error") . ": A password for database user is mandatory.</td></tr>";
1905
                            } else {
1906
                                // Create user
1907
                                $result = $db->DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_name seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_host seems to be never defined.
Loading history...
1908
1909
                                // Create user bis
1910
                                if ($databasefortest == 'mysql') {
1911
                                    if (!in_array($dolibarr_main_db_host, ['127.0.0.1', '::1', 'localhost', 'localhost.local'])) {
1912
                                        $resultbis = $db->DDLCreateUser('%', $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name);
1913
                                    }
1914
                                }
1915
1916
                                if ($result > 0 && $resultbis > 0) {
1917
                                    print '<tr><td>';
1918
                                    print $this->langs->trans("UserCreation") . ' : ';
1919
                                    print $dolibarr_main_db_user;
1920
                                    print '</td>';
1921
                                    print '<td><img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/ok.png" alt="Ok"></td></tr>';
1922
                                } else {
1923
                                    if (
1924
                                        $db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS'
1925
                                        || $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
1926
                                        || $db->errno() == 'DB_ERROR_USER_ALREADY_EXISTS'
1927
                                    ) {
1928
                                        dolibarr_install_syslog("step1: user already exists");
1929
                                        print '<tr><td>';
1930
                                        print $this->langs->trans("UserCreation") . ' : ';
1931
                                        print $dolibarr_main_db_user;
1932
                                        print '</td>';
1933
                                        print '<td>' . $this->langs->trans("LoginAlreadyExists") . '</td></tr>';
1934
                                    } else {
1935
                                        dolibarr_install_syslog("step1: failed to create user", LOG_ERR);
1936
                                        print '<tr><td>';
1937
                                        print $this->langs->trans("UserCreation") . ' : ';
1938
                                        print $dolibarr_main_db_user;
1939
                                        print '</td>';
1940
                                        print '<td>' . $this->langs->trans("Error") . ': ' . $db->errno() . ' ' . $db->error() . ($db->error ? '. ' . $db->error : '') . "</td></tr>";
1941
                                    }
1942
                                }
1943
                            }
1944
1945
                            $db->close();
1946
                        } else {
1947
                            print '<tr><td>';
1948
                            print $this->langs->trans("UserCreation") . ' : ';
1949
                            print $dolibarr_main_db_user;
1950
                            print '</td>';
1951
                            print '<td><img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/error..png" alt="Error"></td>';
1952
                            print '</tr>';
1953
1954
                            // warning message due to connection failure
1955
                            print '<tr><td colspan="2"><br>';
1956
                            print $this->langs->trans("YouAskDatabaseCreationSoDolibarrNeedToConnect", $dolibarr_main_db_user, $dolibarr_main_db_host, $userroot);
1957
                            print '<br>';
1958
                            print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
1959
                            print $this->langs->trans("ErrorGoBackAndCorrectParameters") . '<br><br>';
1960
                            print '</td></tr>';
1961
1962
                            $error++;
1963
                        }
1964
                    }
1965
                }   // end of user account creation
1966
1967
1968
                // If database creation was asked, we create it
1969
                if (!$error && (isset($this->db_create_database) && ($this->db_create_database == "1" || $this->db_create_database == "on"))) {
1970
                    dolibarr_install_syslog("step1: create database: " . $dolibarr_main_db_name . " " . $dolibarr_main_db_character_set . " " . $dolibarr_main_db_collation . " " . $dolibarr_main_db_user);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_collation seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_character_set seems to be never defined.
Loading history...
1971
                    $newdb = getDoliDBInstance($this->conf->db->type, $this->conf->db->host, $userroot, $passroot, '', (int)$this->conf->db->port);
1972
                    //print 'eee'.$this->conf->db->type." ".$this->conf->db->host." ".$userroot." ".$passroot." ".$this->conf->db->port." ".$newdb->connected." ".$newdb->forcecharset;exit;
1973
1974
                    if ($newdb->connected) {
1975
                        $result = $newdb->DDLCreateDb($dolibarr_main_db_name, $dolibarr_main_db_character_set, $dolibarr_main_db_collation, $dolibarr_main_db_user);
1976
1977
                        if ($result) {
1978
                            print '<tr><td>';
1979
                            print $this->langs->trans("DatabaseCreation") . " (" . $this->langs->trans("User") . " " . $userroot . ") : ";
1980
                            print $dolibarr_main_db_name;
1981
                            print '</td>';
1982
                            print '<td><img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/ok.png" alt="Ok"></td></tr>';
1983
1984
                            $newdb->select_db($dolibarr_main_db_name);
1985
                            $check1 = $newdb->getDefaultCharacterSetDatabase();
1986
                            $check2 = $newdb->getDefaultCollationDatabase();
1987
                            dolibarr_install_syslog('step1: new database is using charset=' . $check1 . ' collation=' . $check2);
1988
1989
                            // If values differs, we save conf file again
1990
                            //if ($check1 != $dolibarr_main_db_character_set) dolibarr_install_syslog('step1: value for character_set is not the one asked for database creation', LOG_WARNING);
1991
                            //if ($check2 != $dolibarr_main_db_collation)     dolibarr_install_syslog('step1: value for collation is not the one asked for database creation', LOG_WARNING);
1992
                        } else {
1993
                            // warning message
1994
                            print '<tr><td colspan="2"><br>';
1995
                            print $this->langs->trans("ErrorFailedToCreateDatabase", $dolibarr_main_db_name) . '<br>';
1996
                            print $newdb->lasterror() . '<br>';
1997
                            print $this->langs->trans("IfDatabaseExistsGoBackAndCheckCreate");
1998
                            print '<br>';
1999
                            print '</td></tr>';
2000
2001
                            dolibarr_install_syslog('step1: failed to create database ' . $dolibarr_main_db_name . ' ' . $newdb->lasterrno() . ' ' . $newdb->lasterror(), LOG_ERR);
2002
                            $error++;
2003
                        }
2004
                        $newdb->close();
2005
                    } else {
2006
                        print '<tr><td>';
2007
                        print $this->langs->trans("DatabaseCreation") . " (" . $this->langs->trans("User") . " " . $userroot . ") : ";
2008
                        print $dolibarr_main_db_name;
2009
                        print '</td>';
2010
                        print '<td><img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/error..png" alt="Error"></td>';
2011
                        print '</tr>';
2012
2013
                        // warning message
2014
                        print '<tr><td colspan="2"><br>';
2015
                        print $this->langs->trans("YouAskDatabaseCreationSoDolibarrNeedToConnect", $dolibarr_main_db_user, $dolibarr_main_db_host, $userroot);
2016
                        print '<br>';
2017
                        print $this->langs->trans("BecauseConnectionFailedParametersMayBeWrong") . '<br><br>';
2018
                        print $this->langs->trans("ErrorGoBackAndCorrectParameters") . '<br><br>';
2019
                        print '</td></tr>';
2020
2021
                        $error++;
2022
                    }
2023
                }   // end of create database
2024
2025
2026
                // We test access with dolibarr database user (not admin)
2027
                if (!$error) {
2028
                    dolibarr_install_syslog("step1: connection type=" . $this->conf->db->type . " on host=" . $this->conf->db->host . " port=" . $this->conf->db->port . " user=" . $this->conf->db->user . " name=" . $this->conf->db->name);
2029
                    //print "connection de type=".$this->conf->db->type." sur host=".$this->conf->db->host." port=".$this->conf->db->port." user=".$this->conf->db->user." name=".$this->conf->db->name;
2030
2031
                    $db = getDoliDBInstance($this->conf->db->type, $this->conf->db->host, $this->conf->db->user, $this->conf->db->pass, $this->conf->db->name, (int)$this->conf->db->port);
2032
2033
                    if ($db->connected) {
2034
                        dolibarr_install_syslog("step1: connection to server by user " . $this->conf->db->user . " ok");
2035
                        print "<tr><td>";
2036
                        print $this->langs->trans("ServerConnection") . " (" . $this->langs->trans("User") . " " . $this->conf->db->user . ") : ";
2037
                        print $this->db_host;
2038
                        print "</td><td>";
2039
                        print '<img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/ok.png" alt="Ok">';
2040
                        print "</td></tr>";
2041
2042
                        // server access ok, basic access ok
2043
                        if ($db->database_selected) {
2044
                            dolibarr_install_syslog("step1: connection to database " . $this->conf->db->name . " by user " . $this->conf->db->user . " ok");
2045
                            print "<tr><td>";
2046
                            print $this->langs->trans("DatabaseConnection") . " (" . $this->langs->trans("User") . " " . $this->conf->db->user . ") : ";
2047
                            print $this->db_name;
2048
                            print "</td><td>";
2049
                            print '<img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/ok.png" alt="Ok">';
2050
                            print "</td></tr>";
2051
2052
                            $error = 0;
2053
                        } else {
2054
                            dolibarr_install_syslog("step1: connection to database " . $this->conf->db->name . " by user " . $this->conf->db->user . " failed", LOG_ERR);
2055
                            print "<tr><td>";
2056
                            print $this->langs->trans("DatabaseConnection") . " (" . $this->langs->trans("User") . " " . $this->conf->db->user . ") : ";
2057
                            print $this->db_name;
2058
                            print '</td><td>';
2059
                            print '<img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/error..png" alt="Error">';
2060
                            print "</td></tr>";
2061
2062
                            // warning message
2063
                            print '<tr><td colspan="2"><br>';
2064
                            print $this->langs->trans('CheckThatDatabasenameIsCorrect', $dolibarr_main_db_name) . '<br>';
2065
                            print $this->langs->trans('IfAlreadyExistsCheckOption') . '<br>';
2066
                            print $this->langs->trans("ErrorGoBackAndCorrectParameters") . '<br><br>';
2067
                            print '</td></tr>';
2068
2069
                            $error++;
2070
                        }
2071
                    } else {
2072
                        dolibarr_install_syslog("step1: connection to server by user " . $this->conf->db->user . " failed", LOG_ERR);
2073
                        print "<tr><td>";
2074
                        print $this->langs->trans("ServerConnection") . " (" . $this->langs->trans("User") . " " . $this->conf->db->user . ") : ";
2075
                        print $this->db_host;
2076
                        print '</td><td>';
2077
                        print '<img src="' . $this->config->file->main_url . '/Templates/theme/' . $this->config->main->theme . '/img/error..png" alt="Error">';
2078
                        print "</td></tr>";
2079
2080
                        // warning message
2081
                        print '<tr><td colspan="2"><br>';
2082
                        print $this->langs->trans("ErrorConnection", $this->conf->db->host, $this->conf->db->name, $this->conf->db->user);
2083
                        print $this->langs->trans('IfLoginDoesNotExistsCheckCreateUser') . '<br>';
2084
                        print $this->langs->trans("ErrorGoBackAndCorrectParameters") . '<br><br>';
2085
                        print '</td></tr>';
2086
2087
                        $error++;
2088
                    }
2089
                }
2090
            }
2091
2092
            print '</table>';
2093
        }
2094
2095
        $ret = 0;
2096
        if ($error && isset($argv[1])) {
2097
            $ret = 1;
2098
        }
2099
        dolibarr_install_syslog("Exit " . $ret);
2100
2101
        dolibarr_install_syslog("--- step1: end");
2102
2103
// Return code if ran from command line
2104
        if ($ret) {
2105
            exit($ret);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
2106
        }
2107
2108
2109
        return true;
2110
    }
2111
2112
    /**
2113
     *  Save configuration file. No particular permissions are set by installer.
2114
     *
2115
     * @param string $conffile Path to conf file to generate/update
2116
     *
2117
     * @return integer
2118
     */
2119
    function write_conf_file($conffile)
2120
    {
2121
        $error = 0;
2122
2123
        $config = Globals::getConfig();
2124
2125
        $key = md5(uniqid(mt_rand(), true)); // Generate random hash
2126
2127
        $fp = fopen("$conffile", "w");
2128
        if ($fp) {
2129
            clearstatcache();
2130
2131
            fwrite($fp, '<?php' . "\n");
2132
            fwrite($fp, '//' . "\n");
2133
            fwrite($fp, '// File generated by Dolibarr installer ' . DOL_VERSION . ' on ' . dol_print_date(dol_now(), '') . "\n");
2134
            fwrite($fp, '//' . "\n");
2135
            fwrite($fp, '// Take a look at conf.php.example file for an example of ' . $conffile . ' file' . "\n");
2136
            fwrite($fp, '// and explanations for all possibles parameters.' . "\n");
2137
            fwrite($fp, '//' . "\n");
2138
2139
            fwrite($fp, '$dolibarr_main_url_root=\'' . dol_escape_php(trim($this->main_url), 1) . '\';');
2140
            fwrite($fp, "\n");
2141
2142
            fwrite($fp, '$dolibarr_main_document_root="' . dol_escape_php(dol_sanitizePathName(trim($this->main_dir))) . '";');
2143
            fwrite($fp, "\n");
2144
2145
            fwrite($fp, $this->main_use_alt_dir . '$dolibarr_main_url_root_alt=\'' . dol_escape_php(trim("/" . $this->main_alt_dir_name), 1) . '\';');
2146
            fwrite($fp, "\n");
2147
2148
            fwrite($fp, $this->main_use_alt_dir . '$dolibarr_main_document_root_alt="' . dol_escape_php(dol_sanitizePathName(trim($this->main_dir . "/" . $this->main_alt_dir_name))) . '";');
2149
            fwrite($fp, "\n");
2150
2151
            fwrite($fp, '$dolibarr_main_data_root="' . dol_escape_php(dol_sanitizePathName(trim($this->main_data_dir))) . '";');
2152
            fwrite($fp, "\n");
2153
2154
            fwrite($fp, '$dolibarr_main_db_host=\'' . dol_escape_php(trim($this->db_host), 1) . '\';');
2155
            fwrite($fp, "\n");
2156
2157
            fwrite($fp, '$dolibarr_main_db_port=\'' . ((int)$this->db_port) . '\';');
2158
            fwrite($fp, "\n");
2159
2160
            fwrite($fp, '$dolibarr_main_db_name=\'' . dol_escape_php(trim($this->db_name), 1) . '\';');
2161
            fwrite($fp, "\n");
2162
2163
            fwrite($fp, '$dolibarr_main_db_prefix=\'' . dol_escape_php(trim($this->main_db_prefix), 1) . '\';');
2164
            fwrite($fp, "\n");
2165
2166
            fwrite($fp, '$dolibarr_main_db_user=\'' . dol_escape_php(trim($this->db_user), 1) . '\';');
2167
            fwrite($fp, "\n");
2168
            fwrite($fp, '$dolibarr_main_db_pass=\'' . dol_escape_php(trim($this->db_pass), 1) . '\';');
2169
            fwrite($fp, "\n");
2170
2171
            fwrite($fp, '$dolibarr_main_db_type=\'' . dol_escape_php(trim($this->db_type), 1) . '\';');
2172
            fwrite($fp, "\n");
2173
2174
            fwrite($fp, '$dolibarr_main_db_character_set=\'' . dol_escape_php(trim($this->db_character_set), 1) . '\';');
2175
            fwrite($fp, "\n");
2176
2177
            fwrite($fp, '$dolibarr_main_db_collation=\'' . dol_escape_php(trim($this->db_collation), 1) . '\';');
2178
            fwrite($fp, "\n");
2179
2180
            // Authentication
2181
            fwrite($fp, '// Authentication settings');
2182
            fwrite($fp, "\n");
2183
2184
            fwrite($fp, '$dolibarr_main_authentication=\'dolibarr\';');
2185
            fwrite($fp, "\n\n");
2186
2187
            fwrite($fp, '//$dolibarr_main_demo=\'autologin,autopass\';');
2188
            fwrite($fp, "\n");
2189
2190
            fwrite($fp, '// Security settings');
2191
            fwrite($fp, "\n");
2192
2193
            fwrite($fp, '$dolibarr_main_prod=\'0\';');
2194
            fwrite($fp, "\n");
2195
2196
            fwrite($fp, '$dolibarr_main_force_https=\'' . dol_escape_php($this->main_force_https, 1) . '\';');
2197
            fwrite($fp, "\n");
2198
2199
            fwrite($fp, '$dolibarr_main_restrict_os_commands=\'mariadb-dump, mariadb, mysqldump, mysql, pg_dump, pgrestore, clamdscan, clamscan.exe\';');
2200
            fwrite($fp, "\n");
2201
2202
            fwrite($fp, '$dolibarr_nocsrfcheck=\'0\';');
2203
            fwrite($fp, "\n");
2204
2205
            fwrite($fp, '$dolibarr_main_instance_unique_id=\'' . dol_escape_php($key, 1) . '\';');
2206
            fwrite($fp, "\n");
2207
2208
            fwrite($fp, '$dolibarr_mailing_limit_sendbyweb=\'0\';');
2209
            fwrite($fp, "\n");
2210
            fwrite($fp, '$dolibarr_mailing_limit_sendbycli=\'0\';');
2211
            fwrite($fp, "\n");
2212
2213
            // Write params to overwrites default lib path
2214
            fwrite($fp, "\n");
2215
            if (empty($force_dolibarr_lib_FPDF_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_FPDF_PATH seems to never exist and therefore empty should always be true.
Loading history...
2216
                fwrite($fp, '//');
2217
                $force_dolibarr_lib_FPDF_PATH = '';
2218
            }
2219
            fwrite($fp, '$dolibarr_lib_FPDF_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_FPDF_PATH)) . '";');
2220
            fwrite($fp, "\n");
2221
            if (empty($force_dolibarr_lib_TCPDF_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_TCPDF_PATH seems to never exist and therefore empty should always be true.
Loading history...
2222
                fwrite($fp, '//');
2223
                $force_dolibarr_lib_TCPDF_PATH = '';
2224
            }
2225
            fwrite($fp, '$dolibarr_lib_TCPDF_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_TCPDF_PATH)) . '";');
2226
            fwrite($fp, "\n");
2227
            if (empty($force_dolibarr_lib_FPDI_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_FPDI_PATH seems to never exist and therefore empty should always be true.
Loading history...
2228
                fwrite($fp, '//');
2229
                $force_dolibarr_lib_FPDI_PATH = '';
2230
            }
2231
            fwrite($fp, '$dolibarr_lib_FPDI_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_FPDI_PATH)) . '";');
2232
            fwrite($fp, "\n");
2233
            if (empty($force_dolibarr_lib_TCPDI_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_TCPDI_PATH seems to never exist and therefore empty should always be true.
Loading history...
2234
                fwrite($fp, '//');
2235
                $force_dolibarr_lib_TCPDI_PATH = '';
2236
            }
2237
            fwrite($fp, '$dolibarr_lib_TCPDI_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_TCPDI_PATH)) . '";');
2238
            fwrite($fp, "\n");
2239
            if (empty($force_dolibarr_lib_GEOIP_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_GEOIP_PATH seems to never exist and therefore empty should always be true.
Loading history...
2240
                fwrite($fp, '//');
2241
                $force_dolibarr_lib_GEOIP_PATH = '';
2242
            }
2243
            fwrite($fp, '$dolibarr_lib_GEOIP_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_GEOIP_PATH)) . '";');
2244
            fwrite($fp, "\n");
2245
            if (empty($force_dolibarr_lib_NUSOAP_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_NUSOAP_PATH seems to never exist and therefore empty should always be true.
Loading history...
2246
                fwrite($fp, '//');
2247
                $force_dolibarr_lib_NUSOAP_PATH = '';
2248
            }
2249
            fwrite($fp, '$dolibarr_lib_NUSOAP_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_NUSOAP_PATH)) . '";');
2250
            fwrite($fp, "\n");
2251
            if (empty($force_dolibarr_lib_ODTPHP_PATH)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_ODTPHP_PATH does not exist. Did you maybe mean $force_dolibarr_lib_ODTPHP_PATHTOPCLZIP?
Loading history...
2252
                fwrite($fp, '//');
2253
                $force_dolibarr_lib_ODTPHP_PATH = '';
2254
            }
2255
            fwrite($fp, '$dolibarr_lib_ODTPHP_PATH="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_ODTPHP_PATH)) . '";');
2256
            fwrite($fp, "\n");
2257
            if (empty($force_dolibarr_lib_ODTPHP_PATHTOPCLZIP)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_lib_ODTPHP_PATHTOPCLZIP seems to never exist and therefore empty should always be true.
Loading history...
2258
                fwrite($fp, '//');
2259
                $force_dolibarr_lib_ODTPHP_PATHTOPCLZIP = '';
2260
            }
2261
            fwrite($fp, '$dolibarr_lib_ODTPHP_PATHTOPCLZIP="' . dol_escape_php(dol_sanitizePathName($force_dolibarr_lib_ODTPHP_PATHTOPCLZIP)) . '";');
2262
            fwrite($fp, "\n");
2263
            if (empty($force_dolibarr_js_CKEDITOR)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_js_CKEDITOR seems to never exist and therefore empty should always be true.
Loading history...
2264
                fwrite($fp, '//');
2265
                $force_dolibarr_js_CKEDITOR = '';
2266
            }
2267
            fwrite($fp, '$dolibarr_js_CKEDITOR=\'' . dol_escape_php($force_dolibarr_js_CKEDITOR, 1) . '\';');
2268
            fwrite($fp, "\n");
2269
            if (empty($force_dolibarr_js_JQUERY)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_js_JQUERY seems to never exist and therefore empty should always be true.
Loading history...
2270
                fwrite($fp, '//');
2271
                $force_dolibarr_js_JQUERY = '';
2272
            }
2273
            fwrite($fp, '$dolibarr_js_JQUERY=\'' . dol_escape_php($force_dolibarr_js_JQUERY, 1) . '\';');
2274
            fwrite($fp, "\n");
2275
            if (empty($force_dolibarr_js_JQUERY_UI)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_js_JQUERY_UI does not exist. Did you maybe mean $force_dolibarr_js_JQUERY?
Loading history...
2276
                fwrite($fp, '//');
2277
                $force_dolibarr_js_JQUERY_UI = '';
2278
            }
2279
            fwrite($fp, '$dolibarr_js_JQUERY_UI=\'' . dol_escape_php($force_dolibarr_js_JQUERY_UI, 1) . '\';');
2280
            fwrite($fp, "\n");
2281
2282
            // Write params to overwrites default font path
2283
            fwrite($fp, "\n");
2284
            if (empty($force_dolibarr_font_DOL_DEFAULT_TTF)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_font_DOL_DEFAULT_TTF seems to never exist and therefore empty should always be true.
Loading history...
2285
                fwrite($fp, '//');
2286
                $force_dolibarr_font_DOL_DEFAULT_TTF = '';
2287
            }
2288
            fwrite($fp, '$dolibarr_font_DOL_DEFAULT_TTF=\'' . dol_escape_php($force_dolibarr_font_DOL_DEFAULT_TTF, 1) . '\';');
2289
            fwrite($fp, "\n");
2290
            if (empty($force_dolibarr_font_DOL_DEFAULT_TTF_BOLD)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_dolibarr_font_DOL_DEFAULT_TTF_BOLD does not exist. Did you maybe mean $force_dolibarr_font_DOL_DEFAULT_TTF?
Loading history...
2291
                fwrite($fp, '//');
2292
                $force_dolibarr_font_DOL_DEFAULT_TTF_BOLD = '';
2293
            }
2294
            fwrite($fp, '$dolibarr_font_DOL_DEFAULT_TTF_BOLD=\'' . dol_escape_php($force_dolibarr_font_DOL_DEFAULT_TTF_BOLD, 1) . '\';');
2295
            fwrite($fp, "\n");
2296
2297
            // Other
2298
            fwrite($fp, '$dolibarr_main_distrib=\'' . dol_escape_php(trim($this->dolibarr_main_distrib), 1) . '\';');
2299
            fwrite($fp, "\n");
2300
2301
            fclose($fp);
2302
2303
            if (file_exists("$conffile")) {
2304
                include $conffile; // force config reload, do not put include_once
2305
                $this->conf($this->main_dir);
2306
2307
                print "<tr><td>";
2308
                print $this->langs->trans("SaveConfigurationFile");
2309
                print ' <strong>' . $conffile . '</strong>';
2310
                print "</td><td>";
2311
                print '<img src="' . $this->config->file->main_url . '/' . $this->config->main->theme . '/img/svg/ok.png" alt="Ok">';
2312
                print "</td></tr>";
2313
            } else {
2314
                $error++;
2315
            }
2316
        }
2317
2318
        return $error;
2319
    }
2320
2321
    /**
2322
     * Load conf file (file must exists)
2323
     *
2324
     * @param string $dolibarr_main_document_root Root directory of Dolibarr bin files
2325
     *
2326
     * @return  int                                             Return integer <0 if KO, >0 if OK
2327
     */
2328
    function conf($dolibarr_main_document_root = BASE_PATH)
2329
    {
2330
        $this->conf = Globals::getConf();
2331
        $this->conf->db->type = trim($this->db_type);
0 ignored issues
show
Bug introduced by
The property db_type does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_types?
Loading history...
2332
        $this->conf->db->host = trim($this->db_host);
0 ignored issues
show
Bug Best Practice introduced by
The property db_host does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
2333
        $this->conf->db->port = trim($this->db_port);
0 ignored issues
show
Bug Best Practice introduced by
The property db_port does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
2334
        $this->conf->db->name = trim($this->db_name);
0 ignored issues
show
Bug Best Practice introduced by
The property db_name does not exist on DoliModules\Install\Controller\InstallController. Did you maybe forget to declare it?
Loading history...
2335
        $this->conf->db->user = trim($this->db_user);
0 ignored issues
show
Bug introduced by
The property db_user does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_user_root?
Loading history...
2336
        $this->conf->db->pass = (empty($this->db_pass) ? '' : trim($this->db_pass));
0 ignored issues
show
Bug introduced by
The property db_pass does not exist on DoliModules\Install\Controller\InstallController. Did you mean db_pass_root?
Loading history...
2337
2338
        if (empty($character_set_client)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $character_set_client seems to never exist and therefore empty should always be true.
Loading history...
2339
            $character_set_client = "UTF-8";
2340
        }
2341
        $this->conf->file->character_set_client = strtoupper($character_set_client);
2342
        // Unique id of instance
2343
        $this->conf->file->instance_unique_id = empty($dolibarr_main_instance_unique_id) ? (empty($dolibarr_main_cookie_cryptkey) ? '' : $dolibarr_main_cookie_cryptkey) : $dolibarr_main_instance_unique_id;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_instance_unique_id seems to never exist and therefore empty should always be true.
Loading history...
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_cookie_cryptkey does not exist. Did you maybe mean $dolibarr_main_db_cryptkey?
Loading history...
2344
        if (empty($dolibarr_main_db_character_set)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_character_set seems to never exist and therefore empty should always be true.
Loading history...
2345
            $dolibarr_main_db_character_set = ($this->conf->db->type == 'MySqliEngine' ? 'utf8' : '');
2346
        }
2347
        $this->conf->db->character_set = $dolibarr_main_db_character_set;
2348
        if (empty($dolibarr_main_db_collation)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_collation seems to never exist and therefore empty should always be true.
Loading history...
2349
            $dolibarr_main_db_collation = ($this->conf->db->type == 'MySqliEngine' ? 'utf8_unicode_ci' : '');
2350
        }
2351
        $this->conf->db->dolibarr_main_db_collation = $dolibarr_main_db_collation;
2352
        if (empty($dolibarr_main_db_encryption)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_encryption seems to never exist and therefore empty should always be true.
Loading history...
2353
            $dolibarr_main_db_encryption = 0;
2354
        }
2355
        $this->conf->db->dolibarr_main_db_encryption = $dolibarr_main_db_encryption;
2356
        if (empty($dolibarr_main_db_cryptkey)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_cryptkey seems to never exist and therefore empty should always be true.
Loading history...
2357
            $dolibarr_main_db_cryptkey = '';
2358
        }
2359
        $this->conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey;
2360
2361
        // Force usage of log file for install and upgrades
2362
        $this->conf->modules['syslog'] = 'syslog';
2363
        $this->conf->global->SYSLOG_LEVEL = constant('LOG_DEBUG');
2364
        if (!defined('SYSLOG_HANDLERS')) {
2365
            define('SYSLOG_HANDLERS', '["mod_syslog_file"]');
2366
        }
2367
        if (!defined('SYSLOG_FILE')) {  // To avoid warning on systems with constant already defined
2368
            if (@is_writable('/tmp')) {
2369
                define('SYSLOG_FILE', '/tmp/dolibarr_install.log');
2370
            } elseif (!empty($_ENV["TMP"]) && @is_writable($_ENV["TMP"])) {
2371
                define('SYSLOG_FILE', $_ENV["TMP"] . '/dolibarr_install.log');
2372
            } elseif (!empty($_ENV["TEMP"]) && @is_writable($_ENV["TEMP"])) {
2373
                define('SYSLOG_FILE', $_ENV["TEMP"] . '/dolibarr_install.log');
2374
            } elseif (@is_writable('../../../../') && @file_exists('../../../../startdoliwamp.bat')) {
2375
                define('SYSLOG_FILE', '../../../../dolibarr_install.log'); // For DoliWamp
2376
            } elseif (@is_writable('../../')) {
2377
                define('SYSLOG_FILE', '../../dolibarr_install.log'); // For others
2378
            }
2379
            //print 'SYSLOG_FILE='.SYSLOG_FILE;exit;
2380
        }
2381
        if (defined('SYSLOG_FILE')) {
2382
            $this->conf->global->SYSLOG_FILE = constant('SYSLOG_FILE');
2383
        }
2384
        if (!defined('SYSLOG_FILE_NO_ERROR')) {
2385
            define('SYSLOG_FILE_NO_ERROR', 1);
2386
        }
2387
2388
        /**
2389
         * TODO: Pending
2390
         *
2391
         * // We init log handler for install
2392
         * $handlers = array('mod_syslog_file');
2393
         * foreach ($handlers as $handler) {
2394
         * $file = BASE_PATH . '/core/modules/syslog/' . $handler . '.php';
2395
         * if (!file_exists($file)) {
2396
         * throw new Exception('Missing log handler file ' . $handler . '.php');
2397
         * }
2398
         *
2399
         * require_once $file;
2400
         * $loghandlerinstance = new $handler();
2401
         * if (!$loghandlerinstance instanceof LogHandlerInterface) {
2402
         * throw new Exception('Log handler does not extend LogHandlerInterface');
2403
         * }
2404
         *
2405
         * if (empty($this->conf->loghandlers[$handler])) {
2406
         * $this->conf->loghandlers[$handler] = $loghandlerinstance;
2407
         * }
2408
         * }
2409
         */
2410
2411
        return 1;
2412
    }
2413
2414
    private function _checkBrowser()
0 ignored issues
show
Unused Code introduced by
The method _checkBrowser() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2415
    {
2416
        $useragent = $_SERVER['HTTP_USER_AGENT'];
2417
        if (empty($useragent)) {
2418
            return false;
2419
        }
2420
2421
        $tmp = getBrowserInfo($_SERVER["HTTP_USER_AGENT"]);
2422
        $browsername = $tmp['browsername'];
2423
        $browserversion = $tmp['browserversion'];
2424
        if ($browsername == 'ie' && $browserversion < 7) {
2425
            $result = [];
2426
            $result['ok'] = true;
2427
            $result['icon'] = 'warning';
2428
            $result['text'] = $this->langs->trans("WarningBrowserTooOld");
2429
            return $result;
2430
        }
2431
2432
        return false;
2433
    }
2434
2435
    private function _checkMinPhp()
0 ignored issues
show
Unused Code introduced by
The method _checkMinPhp() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2436
    {
2437
        $arrayphpminversionerror = [7, 0, 0];
2438
        $arrayphpminversionwarning = [7, 1, 0];
2439
2440
        $result = [];
2441
        $result['ok'] = true;
2442
2443
        if (versioncompare(versionphparray(), $arrayphpminversionerror) < 0) {        // Minimum to use (error if lower)
2444
            $result['ok'] = false;
2445
            $result['icon'] = 'error';
2446
            $result['text'] = $this->langs->trans("ErrorPHPVersionTooLow", versiontostring($arrayphpminversionerror));
2447
        } elseif (versioncompare(versionphparray(), $arrayphpminversionwarning) < 0) {    // Minimum supported (warning if lower)
2448
            $result['icon'] = 'warning';
2449
            $result['text'] = $this->langs->trans("ErrorPHPVersionTooLow", versiontostring($arrayphpminversionwarning));
2450
        } else {
2451
            $result['icon'] = 'ok';
2452
            $result['text'] = $this->langs->trans("PHPVersion") . " " . versiontostring(versionphparray());
2453
        }
2454
2455
        if (empty($force_install_nophpinfo)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $force_install_nophpinfo seems to never exist and therefore empty should always be true.
Loading history...
2456
            $result['text'] .= ' (<a href="phpinfo.php" target="_blank" rel="noopener noreferrer">' . $this->langs->trans("MoreInformation") . '</a>)';
2457
        }
2458
2459
        return $result;
2460
    }
2461
2462
    private function _checkMaxPhp()
0 ignored issues
show
Unused Code introduced by
The method _checkMaxPhp() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2463
    {
2464
        $arrayphpmaxversionwarning = [8, 2, 0];
2465
        if (versioncompare(versionphparray(), $arrayphpmaxversionwarning) > 0 && versioncompare(versionphparray(), $arrayphpmaxversionwarning) < 3) {        // Maximum to use (warning if higher)
2466
            $result = [];
2467
            $result['ok'] = false;
2468
            $result['icon'] = 'error';
2469
            $result['text'] = $this->langs->trans("ErrorPHPVersionTooHigh", versiontostring($arrayphpmaxversionwarning));
2470
            return $result;
2471
        }
2472
2473
        return false;
2474
    }
2475
2476
    private function _checkGetPostSupport()
0 ignored issues
show
Unused Code introduced by
The method _checkGetPostSupport() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2477
    {
2478
        $result = [];
2479
        $result['ok'] = true;
2480
        if (empty($_GET) || empty($_POST)) {   // We must keep $_GET and $_POST here
2481
            $result['icon'] = 'warning';
2482
            $result['text'] = $this->langs->trans("PHPSupportPOSTGETKo") . ' (<a href="' . dol_escape_htmltag($_SERVER["PHP_SELF"]) . '?testget=ok">' . $this->langs->trans("Recheck") . '</a>)';
2483
        } else {
2484
            $result['icon'] = 'ok';
2485
            $result['text'] = $this->langs->trans("PHPSupportPOSTGETOk");
2486
        }
2487
        return $result;
2488
    }
2489
2490
    private function _checkSessionId()
0 ignored issues
show
Unused Code introduced by
The method _checkSessionId() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2491
    {
2492
        $result = [];
2493
        $result['ok'] = function_exists("session_id");
2494
        if ($result['ok']) {
2495
            $result['icon'] = 'ok';
2496
            $result['text'] = $this->langs->trans("PHPSupportSessions");
2497
        } else {
2498
            $result['icon'] = 'error';
2499
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupportSessions");
2500
        }
2501
        return $result;
2502
    }
2503
2504
    private function _checkMbStringExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkMbStringExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2505
    {
2506
        $result = [];
2507
        $result['ok'] = extension_loaded("mbstring");
2508
        if (!$result['ok']) {
2509
            $result['icon'] = 'error';
2510
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "MBString");
2511
        } else {
2512
            $result['icon'] = 'ok';
2513
            $result['text'] = $this->langs->trans("PHPSupport", "MBString");
2514
        }
2515
        return $result;
2516
    }
2517
2518
    private function _checkJsonExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkJsonExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2519
    {
2520
        $result = [];
2521
        $result['ok'] = extension_loaded("json");
2522
        if (!$result['ok']) {
2523
            $result['icon'] = 'error';
2524
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "JSON");
2525
        } else {
2526
            $result['icon'] = 'ok';
2527
            $result['text'] = $this->langs->trans("PHPSupport", "JSON");
2528
        }
2529
        return $result;
2530
    }
2531
2532
    private function _checkGdExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkGdExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2533
    {
2534
        $result = [];
2535
        $result['ok'] = true;
2536
        if (!function_exists("imagecreate")) {
2537
            $result['icon'] = 'warning';
2538
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "GD");
2539
        } else {
2540
            $result['icon'] = 'ok';
2541
            $result['text'] = $this->langs->trans("PHPSupport", "GD");
2542
        }
2543
        return $result;
2544
    }
2545
2546
    private function _checkCurlExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkCurlExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2547
    {
2548
        $result = [];
2549
        $result['ok'] = true;
2550
        if (!function_exists("curl_init")) {
2551
            $result['icon'] = 'warning';
2552
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "Curl");
2553
        } else {
2554
            $result['icon'] = 'ok';
2555
            $result['text'] = $this->langs->trans("PHPSupport", "Curl");
2556
        }
2557
        return $result;
2558
    }
2559
2560
    private function _checkCalendarExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkCalendarExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2561
    {
2562
        $result = [];
2563
        $result['ok'] = function_exists("easter_date");
2564
        if (!$result['ok']) {
2565
            $result['icon'] = 'error';
2566
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "Calendar");
2567
        } else {
2568
            $result['icon'] = 'ok';
2569
            $result['text'] = $this->langs->trans("PHPSupport", "Calendar");
2570
        }
2571
        return $result;
2572
    }
2573
2574
    private function _checkXmlExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkXmlExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2575
    {
2576
        $result = [];
2577
        $result['ok'] = function_exists("simplexml_load_string");
2578
        if (!$result['ok']) {
2579
            $result['icon'] = 'error';
2580
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "Xml");
2581
        } else {
2582
            $result['icon'] = 'ok';
2583
            $result['text'] = $this->langs->trans("PHPSupport", "Xml");
2584
        }
2585
        return $result;
2586
    }
2587
2588
    private function _checkUtfExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkUtfExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2589
    {
2590
        $result = [];
2591
        $result['ok'] = function_exists("utf8_encode");
2592
        if (!$result['ok']) {
2593
            $result['icon'] = 'error';
2594
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "UTF8");
2595
        } else {
2596
            $result['icon'] = 'ok';
2597
            $result['text'] = $this->langs->trans("PHPSupport", "UTF8");
2598
        }
2599
        return $result;
2600
    }
2601
2602
    private function _checkIntlExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkIntlExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2603
    {
2604
        if (empty($_SERVER["SERVER_ADMIN"]) || $_SERVER["SERVER_ADMIN"] != 'doliwamp@localhost') {
2605
            $result = [];
2606
            $result['ok'] = function_exists("locale_get_primary_language") && function_exists("locale_get_region");
2607
            if (!$result['ok']) {
2608
                $result['icon'] = 'error';
2609
                $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "Intl");
2610
            } else {
2611
                $result['icon'] = 'ok';
2612
                $result['text'] = $this->langs->trans("PHPSupport", "Intl");
2613
            }
2614
            return $result;
2615
        }
2616
2617
        return false;
2618
    }
2619
2620
    private function _checkImapExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkImapExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2621
    {
2622
        if (PHP_VERSION_ID > 80300) {
2623
            return false;
2624
        }
2625
2626
        $result = [];
2627
        $result['ok'] = function_exists("imap_open");
2628
        if (!$result['ok']) {
2629
            $result['icon'] = 'error';
2630
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "IMAP");
2631
        } else {
2632
            $result['icon'] = 'ok';
2633
            $result['text'] = $this->langs->trans("PHPSupport", "IMAP");
2634
        }
2635
        return $result;
2636
    }
2637
2638
    private function _checkZipExtension()
0 ignored issues
show
Unused Code introduced by
The method _checkZipExtension() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2639
    {
2640
        $result = [];
2641
        $result['ok'] = class_exists('ZipArchive');
2642
        if (!$result['ok']) {
2643
            $result['icon'] = 'error';
2644
            $result['text'] = $this->langs->trans("ErrorPHPDoesNotSupport", "ZIP");
2645
        } else {
2646
            $result['icon'] = 'ok';
2647
            $result['text'] = $this->langs->trans("PHPSupport", "ZIP");
2648
        }
2649
        return $result;
2650
    }
2651
2652
    private function _checkMemory()
0 ignored issues
show
Unused Code introduced by
The method _checkMemory() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2653
    {
2654
        $memmaxorig = @ini_get("memory_limit");
2655
        if (empty($memmaxorig)) {
2656
            return false;
2657
        }
2658
2659
        $memmax = $memmaxorig;
2660
        $memrequiredorig = '64M';
2661
        $memrequired = 64 * 1024 * 1024;
2662
        preg_match('/([0-9]+)([a-zA-Z]*)/i', $memmax, $reg);
2663
        if ($reg[2]) {
2664
            if (strtoupper($reg[2]) == 'G') {
2665
                $memmax = $reg[1] * 1024 * 1024 * 1024;
2666
            }
2667
            if (strtoupper($reg[2]) == 'M') {
2668
                $memmax = $reg[1] * 1024 * 1024;
2669
            }
2670
            if (strtoupper($reg[2]) == 'K') {
2671
                $memmax = $reg[1] * 1024;
2672
            }
2673
        }
2674
2675
        $result = [];
2676
        $result['ok'] = $memmax >= $memrequired || $memmax == -1;
2677
        if ($result['ok']) {
2678
            $result['icon'] = 'ok';
2679
            $result['text'] = $this->langs->trans("PHPMemoryOK", $memmaxorig, $memrequiredorig);
2680
        } else {
2681
            $result['icon'] = 'warning';
2682
            $result['text'] = $this->langs->trans("PHPMemoryTooLow", $memmaxorig, $memrequiredorig);
2683
        }
2684
        return $result;
2685
    }
2686
2687
    private function _checkConfFile()
0 ignored issues
show
Unused Code introduced by
The method _checkConfFile() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2688
    {
2689
        $result = false;
2690
        $conffile = Config::getDolibarrConfigFilename();
2691
2692
        clearstatcache();
2693
        if (is_readable($conffile) && filesize($conffile) > 8) {
2694
            $this->syslog("check: conf file '" . $conffile . "' already defined");
2695
            return $result;
2696
        }
2697
2698
        // If not, we create it
2699
        $this->syslog("check: we try to create conf file '" . $conffile . "'");
2700
2701
        // First we try by copying example
2702
        if (@copy($conffile . ".example", $conffile)) {
2703
            // Success
2704
            $this->syslog("check: successfully copied file " . $conffile . ".example into " . $conffile);
2705
        } else {
2706
            // If failed, we try to create an empty file
2707
            $this->syslog("check: failed to copy file " . $conffile . ".example into " . $conffile . ". We try to create it.", LOG_WARNING);
2708
2709
            $fp = @fopen($conffile, "w");
2710
            if ($fp) {
2711
                @fwrite($fp, '<?php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fwrite(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

2711
                /** @scrutinizer ignore-unhandled */ @fwrite($fp, '<?php');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2712
                @fwrite($fp, "\n");
2713
                fclose($fp);
2714
            } else {
2715
                $this->syslog("check: failed to create a new file " . $conffile . " into current dir " . getcwd() . ". Please check permissions.", LOG_ERR);
2716
                $result = [];
2717
                $result['ok'] = false;
2718
                $result['icon'] = 'error';
2719
                $result['text'] = $this->langs->trans('ConfFileDoesNotExistsAndCouldNotBeCreated', 'conf.php');
2720
            }
2721
        }
2722
        return $result;
2723
    }
2724
2725
    private function _getDbType()
0 ignored issues
show
Unused Code introduced by
The method _getDbType() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
2726
    {
2727
        $defaultype = !empty($dolibarr_main_db_type) ? $dolibarr_main_db_type : (empty($force_install_type) ? 'mysqli' : $force_install_type);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_type seems to never exist and therefore empty should always be true.
Loading history...
Comprehensibility Best Practice introduced by
The variable $force_install_type seems to never exist and therefore empty should always be true.
Loading history...
2728
2729
        $modules = [];
2730
        $nbok = $nbko = 0;
2731
        $option = '';
2732
    }
2733
}
2734