GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Installer::checkNoncriticalSettings()   B
last analyzed

Complexity

Conditions 8
Paths 32

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 32
nop 0
dl 0
loc 26
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
namespace phpMyFAQ;
4
5
/**
6
 * The Installer class installs phpMyFAQ. Classy.
7
 *
8
 * This Source Code Form is subject to the terms of the Mozilla Public License,
9
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
10
 * obtain one at http://mozilla.org/MPL/2.0/.
11
 *
12
 * @package phpMyFAQ
13
 * @author Florian Anderiasch <[email protected]>
14
 * @copyright 2012-2019 phpMyFAQ Team
15
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
16
 * @link https://www.phpmyfaq.de
17
 * @since 2012-08-27
18
 */
19
20
use Composer\Autoload\ClassLoader;
21
use Elasticsearch\ClientBuilder;
22
use phpMyFAQ\Db\Driver;
23
use phpMyFAQ\Instance\Database;
24
use phpMyFAQ\Instance\Database\Stopwords;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, phpMyFAQ\Stopwords.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
25
use phpMyFAQ\Instance\Elasticsearch;
26
use phpMyFAQ\Instance\Setup;
27
use phpMyFAQ\Instance\Master;
28
29
if (!defined('IS_VALID_PHPMYFAQ')) {
30
    exit();
31
}
32
33
/**
34
 * Class Installer.
35
 *
36
 * @package phpMyFAQ
37
 * @author Florian Anderiasch <[email protected]>
38
 * @copyright 2012-2019 phpMyFAQ Team
39
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
40
 * @link https://www.phpmyfaq.de
41
 * @since 2012-08-27
42
 */
43
class Installer
44
{
45
    /**
46
     * System object.
47
     *
48
     * @var System
49
     */
50
    protected $system;
51
52
    /**
53
     * Array with user rights.
54
     *
55
     * @var array
56
     */
57
    protected $mainRights = [
58
        [
59
            'name' => 'add_user',
60
            'description' => 'Right to add user accounts',
61
        ],
62
        [
63
            'name' => 'edit_user',
64
            'description' => 'Right to edit user accounts',
65
        ],
66
        [
67
            'name' => 'delete_user',
68
            'description' => 'Right to delete user accounts',
69
        ],
70
        //4 => "add_faq",
71
        [
72
            'name' => 'add_faq',
73
            'description' => 'Right to add faq entries',
74
        ],
75
        //5 => "edit_faq",
76
        [
77
            'name' => 'edit_faq',
78
            'description' => 'Right to edit faq entries',
79
        ],
80
        //6 => "delete_faq",
81
        [
82
            'name' => 'delete_faq',
83
            'description' => 'Right to delete faq entries',
84
        ],
85
        //7 => "viewlog",
86
        [
87
            'name' => 'viewlog',
88
            'description' => 'Right to view logfiles',
89
        ],
90
        //8 => "adminlog",
91
        [
92
            'name' => 'adminlog',
93
            'description' => 'Right to view admin log',
94
        ],
95
        //9 => "delcomment",
96
        [
97
            'name' => 'delcomment',
98
            'description' => 'Right to delete comments',
99
        ],
100
        //10 => "addnews",
101
        [
102
            'name' => 'addnews',
103
            'description' => 'Right to add news',
104
        ],
105
        //11 => "editnews",
106
        [
107
            'name' => 'editnews',
108
            'description' => 'Right to edit news',
109
        ],
110
        //12 => "delnews",
111
        [
112
            'name' => 'delnews',
113
            'description' => 'Right to delete news',
114
        ],
115
        //13 => "addcateg",
116
        [
117
            'name' => 'addcateg',
118
            'description' => 'Right to add categories',
119
        ],
120
        //14 => "editcateg",
121
        [
122
            'name' => 'editcateg',
123
            'description' => 'Right to edit categories',
124
        ],
125
        //15 => "delcateg",
126
        [
127
            'name' => 'delcateg',
128
            'description' => 'Right to delete categories',
129
        ],
130
        //16 => "passwd",
131
        [
132
            'name' => 'passwd',
133
            'description' => 'Right to change passwords',
134
        ],
135
        //17 => "editconfig",
136
        [
137
            'name' => 'editconfig',
138
            'description' => 'Right to edit configuration',
139
        ],
140
        //18 => "viewadminlink",
141
        [
142
            'name' => 'viewadminlink',
143
            'description' => 'Right to see the link to the admin section'
144
        ],
145
        //19 => "backup delatt", // Duplicate, removed with 2.7.3
146
        //[
147
        //    'name' => 'delatt',
148
        //    'description' => 'Right to delete attachments'
149
        //],
150
        //20 => "backup",
151
        [
152
            'name' => 'backup',
153
            'description' => 'Right to save backups',
154
        ],
155
        //21 => "restore",
156
        [
157
            'name' => 'restore',
158
            'description' => 'Right to load backups',
159
        ],
160
        //22 => "delquestion",
161
        [
162
            'name' => 'delquestion',
163
            'description' => 'Right to delete questions',
164
        ],
165
        //23 => 'addglossary',
166
        [
167
            'name' => 'addglossary',
168
            'description' => 'Right to add glossary entries',
169
        ],
170
        //24 => 'editglossary',
171
        [
172
            'name' => 'editglossary',
173
            'description' => 'Right to edit glossary entries',
174
        ],
175
        //25 => 'delglossary'
176
        [
177
            'name' => 'delglossary',
178
            'description' => 'Right to delete glossary entries',
179
        ],
180
        //26 => 'changebtrevs'
181
        [
182
            'name' => 'changebtrevs',
183
            'description' => 'Right to edit revisions',
184
        ],
185
        //27 => "addgroup",
186
        [
187
            'name' => 'addgroup',
188
            'description' => 'Right to add group accounts',
189
        ],
190
        //28 => "editgroup",
191
        [
192
            'name' => 'editgroup',
193
            'description' => 'Right to edit group accounts',
194
        ],
195
        //29 => "delgroup",
196
        [
197
            'name' => 'delgroup',
198
            'description' => 'Right to delete group accounts',
199
        ],
200
        //30 => "addtranslation",
201
        [
202
            'name' => 'addtranslation',
203
            'description' => 'Right to add translation',
204
        ],
205
        //31 => "edittranslation",
206
        [
207
            'name' => 'edittranslation',
208
            'description' => 'Right to edit translations',
209
        ],
210
        //32 => "deltranslation",
211
        [
212
            'name' => 'deltranslation',
213
            'description' => 'Right to delete translations',
214
        ],
215
        // 33 => 'approverec'
216
        [
217
            'name' => 'approverec',
218
            'description' => 'Right to approve records',
219
        ],
220
        // 34 => 'addattachment'
221
        [
222
            'name' => 'addattachment',
223
            'description' => 'Right to add attachments',
224
        ],
225
        // 35 => 'editattachment'
226
        [
227
            'name' => 'editattachment',
228
            'description' => 'Right to edit attachments',
229
        ],
230
        // 36 => 'delattachment'
231
        [
232
            'name' => 'delattachment',
233
            'description' => 'Right to delete attachments',
234
        ],
235
        // 37 => 'dlattachment'
236
        [
237
            'name' => 'dlattachment',
238
            'description' => 'Right to download attachments',
239
        ],
240
        // 38 => 'reports'
241
        [
242
            'name' => 'reports',
243
            'description' => 'Right to generate reports',
244
        ],
245
        // 39 => 'addfaq'
246
        [
247
            'name' => 'addfaq',
248
            'description' => 'Right to add FAQs in frontend',
249
        ],
250
        // 40 => 'addquestion'
251
        [
252
            'name' => 'addquestion',
253
            'description' => 'Right to add questions in frontend',
254
        ],
255
        // 41 => 'addcomment'
256
        [
257
            'name' => 'addcomment',
258
            'description' => 'Right to add comments in frontend',
259
        ],
260
        // 42 => 'editinstances'
261
        [
262
            'name' => 'editinstances',
263
            'description' => 'Right to edit multi-site instances',
264
        ],
265
        // 43 => 'addinstances'
266
        [
267
            'name' => 'addinstances',
268
            'description' => 'Right to add multi-site instances',
269
        ],
270
        // 44 => 'delinstances'
271
        [
272
            'name' => 'delinstances',
273
            'description' => 'Right to delete multi-site instances',
274
        ],
275
        [
276
            'name' => 'export',
277
            'description' => 'Right to export the complete FAQ',
278
        ],
279
        [
280
            'name' => 'view_faqs',
281
            'description' => 'Right to view FAQs'
282
        ],
283
        [
284
            'name' => 'view_categories',
285
            'description' => 'Right to view categories'
286
287
        ],
288
        [
289
            'name' => 'view_sections',
290
            'description' => 'Right to view sections'
291
292
        ],
293
        [
294
            'name' => 'view_news',
295
            'description' => 'Right to view news'
296
297
        ],
298
        [
299
            'name' => 'add_section',
300
            'description' => 'Right to add sections'
301
302
        ],
303
        [
304
            'name' => 'edit_section',
305
            'description' => 'Right to edit sections'
306
307
        ],
308
        [
309
            'name' => 'delete_section',
310
            'description' => 'Right to delete sections'
311
312
        ],
313
        [
314
            'name' => 'administrate_sections',
315
            'description' => 'Right to administrate sections'
316
317
        ],
318
        [
319
            'name' => 'administrate_groups',
320
            'description' => 'Right to administrate groups'
321
322
        ],
323
    ];
324
325
    /**
326
     * Configuration array.
327
     *
328
     * @var array
329
     */
330
    protected $_mainConfig = [
331
        'main.currentVersion' => null,
332
        'main.currentApiVersion' => null,
333
        'main.language' => '__PHPMYFAQ_LANGUAGE__',
334
        'main.languageDetection' => 'true',
335
        'main.phpMyFAQToken' => null,
336
        'main.referenceURL' => '__PHPMYFAQ_REFERENCE_URL__',
337
        'main.administrationMail' => '[email protected]',
338
        'main.contactInformations' => '',
339
        'main.enableAdminLog' => 'true',
340
        'main.enableRewriteRules' => 'false',
341
        'main.enableUserTracking' => 'true',
342
        'main.metaDescription' => 'phpMyFAQ should be the answer for all questions in life',
343
        'main.metaKeywords' => '',
344
        'main.metaPublisher' => '__PHPMYFAQ_PUBLISHER__',
345
        'main.send2friendText' => '',
346
        'main.titleFAQ' => 'phpMyFAQ Codename Phobos',
347
        'main.urlValidateInterval' => '86400',
348
        'main.enableWysiwygEditor' => 'true',
349
        'main.enableWysiwygEditorFrontend' => 'false',
350
        'main.enableMarkdownEditor' => 'false',
351
        'main.templateSet' => 'default',
352
        'main.optionalMailAddress' => 'false',
353
        'main.dateFormat' => 'Y-m-d H:i',
354
        'main.maintenanceMode' => 'false',
355
        'main.enableGravatarSupport' => 'false',
356
        'main.enableRssFeeds' => 'true',
357
        'main.enableGzipCompression' => 'true',
358
        'main.enableLinkVerification' => 'true',
359
        'main.customPdfHeader' => '',
360
        'main.customPdfHFooter' => '',
361
        'main.enableSmartAnswering' => 'true',
362
        'main.enableCategoryRestrictions' => 'true',
363
        'main.enableSendToFriend' => 'true',
364
        'main.privacyURL' => '',
365
        'main.enableAutoUpdateHint' => 'true',
366
367
        'records.numberOfRecordsPerPage' => '10',
368
        'records.numberOfShownNewsEntries' => '3',
369
        'records.defaultActivation' => 'false',
370
        'records.defaultAllowComments' => 'false',
371
        'records.enableVisibilityQuestions' => 'false',
372
        'records.numberOfRelatedArticles' => '5',
373
        'records.orderby' => 'id',
374
        'records.sortby' => 'DESC',
375
        'records.orderingPopularFaqs' => 'visits',
376
        'records.disableAttachments' => 'true',
377
        'records.maxAttachmentSize' => '100000',
378
        'records.attachmentsPath' => 'attachments',
379
        'records.attachmentsStorageType' => '0',
380
        'records.enableAttachmentEncryption' => 'false',
381
        'records.defaultAttachmentEncKey' => '',
382
        'records.enableCloseQuestion' => 'false',
383
        'records.enableDeleteQuestion' => 'false',
384
        'records.autosaveActive' => 'false',
385
        'records.autosaveSecs' => '180',
386
        'records.randomSort' => 'false',
387
        'records.allowCommentsForGuests' => 'true',
388
        'records.allowQuestionsForGuests' => 'true',
389
        'records.allowNewFaqsForGuests' => 'true',
390
        'records.hideEmptyCategories' => 'false',
391
        'records.allowDownloadsForGuests' => 'false',
392
        'records.numberMaxStoredRevisions' => '10',
393
        'records.enableAutoRevisions' => 'false',
394
395
        'search.numberSearchTerms' => '10',
396
        'search.relevance' => 'thema,content,keywords',
397
        'search.enableRelevance' => 'false',
398
        'search.enableHighlighting' => 'true',
399
        'search.searchForSolutionId' => 'true',
400
        'search.enableElasticsearch' => 'false',
401
402
        'security.permLevel' => 'basic',
403
        'security.ipCheck' => 'false',
404
        'security.enableLoginOnly' => 'false',
405
        'security.bannedIPs' => '',
406
        'security.ssoSupport' => 'false',
407
        'security.ssoLogoutRedirect' => '',
408
        'security.useSslForLogins' => 'false',
409
        'security.useSslOnly' => 'false',
410
        'security.forcePasswordUpdate' => 'false',
411
        'security.enableRegistration' => 'true',
412
413
        'spam.checkBannedWords' => 'true',
414
        'spam.enableCaptchaCode' => null,
415
        'spam.enableSafeEmail' => 'true',
416
        'spam.manualActivation' => 'true',
417
418
        'socialnetworks.enableTwitterSupport' => 'false',
419
        'socialnetworks.twitterConsumerKey' => '',
420
        'socialnetworks.twitterConsumerSecret' => '',
421
        'socialnetworks.twitterAccessTokenKey' => '',
422
        'socialnetworks.twitterAccessTokenSecret' => '',
423
        'socialnetworks.enableFacebookSupport' => 'false',
424
        'socialnetworks.disableAll' => 'false',
425
426
        'seo.metaTagsHome' => 'index, follow',
427
        'seo.metaTagsFaqs' => 'index, follow',
428
        'seo.metaTagsCategories' => 'index, follow',
429
        'seo.metaTagsPages' => 'index, follow',
430
        'seo.metaTagsAdmin' => 'noindex, nofollow',
431
        'seo.enableXMLSitemap' => 'true',
432
433
        'mail.remoteSMTP' => 'false',
434
        'mail.remoteSMTPServer' => '',
435
        'mail.remoteSMTPUsername' => '',
436
        'mail.remoteSMTPPassword' => '',
437
438
        'ldap.ldapSupport' => 'false',
439
        'ldap.ldap_mapping.name' => 'cn',
440
        'ldap.ldap_mapping.username' => 'samAccountName',
441
        'ldap.ldap_mapping.mail' => 'mail',
442
        'ldap.ldap_mapping.memberOf' => '',
443
        'ldap.ldap_use_domain_prefix' => 'true',
444
        'ldap.ldap_options.LDAP_OPT_PROTOCOL_VERSION' => '3',
445
        'ldap.ldap_options.LDAP_OPT_REFERRALS' => '0',
446
        'ldap.ldap_use_memberOf' => 'false',
447
        'ldap.ldap_use_sasl' => 'false',
448
        'ldap.ldap_use_multiple_servers' => 'false',
449
        'ldap.ldap_use_anonymous_login' => 'false',
450
        'ldap.ldap_use_dynamic_login' => 'false',
451
        'ldap.ldap_dynamic_login_attribute' => 'uid'
452
    ];
453
454
    /**
455
     * Constructor.
456
     *
457
     */
458
    public function __construct()
459
    {
460
        $this->system = new System();
461
        $dynMainConfig = [
462
            'main.currentVersion' => System::getVersion(),
463
            'main.currentApiVersion' => System::getApiVersion(),
464
            'main.phpMyFAQToken' => md5(uniqid(rand())),
465
            'spam.enableCaptchaCode' => (extension_loaded('gd') ? 'true' : 'false')
466
        ];
467
        $this->_mainConfig = array_merge($this->_mainConfig, $dynMainConfig);
468
    }
469
470
    /**
471
     * Check absolutely necessary stuff and die.
472
     */
473
    public function checkBasicStuff()
474
    {
475
        if (!$this->checkMinimumPhpVersion()) {
476
            printf(
477
                '<p class="alert alert-danger">Sorry, but you need PHP %s or later!</p>',
478
                System::VERSION_MINIMUM_PHP
479
            );
480
            System::renderFooter();
481
        }
482
483
        if (!function_exists('date_default_timezone_set')) {
484
            echo '<p class="alert alert-danger">Sorry, but setting a default timezone doesn\'t work in your environment!</p>';
485
            System::renderFooter();
486
        }
487
488 View Code Duplication
        if (!$this->system->checkDatabase()) {
489
            echo '<p class="alert alert-danger">No supported database detected! Please install one of the following'.
490
                ' database systems and enable the corresponding PHP extension in php.ini:</p>';
491
            echo '<ul>';
492
            foreach ($this->system->getSupportedDatabases() as $database) {
493
                printf('    <li>%s</li>', $database[1]);
494
            }
495
            echo '</ul>';
496
            System::renderFooter();
497
        }
498
499 View Code Duplication
        if (!$this->system->checkRequiredExtensions()) {
500
            echo '<p class="alert alert-danger">The following extensions are missing! Please enable the PHP extension(s) in '.
501
                'php.ini.</p>';
502
            echo '<ul>';
503
            foreach ($this->system->getMissingExtensions() as $extension) {
504
                printf('    <li>ext/%s</li>', $extension);
505
            }
506
            echo '</ul>';
507
            System::renderFooter();
508
        }
509
510
        if (!$this->system->checkphpMyFAQInstallation()) {
511
            echo '<p class="alert alert-danger">The file <code>config/database.php</code> was detected. It seems'.
512
                ' you\'re already running a version of phpMyFAQ. Please run the <a href="update.php">update script</a>.'.
513
                '</p>';
514
            System::renderFooter();
515
        }
516
    }
517
518
    /**
519
     * Checks for the minimum PHP requirement and if the database credentials file is readable.
520
     *
521
     * @param string $databaseType
522
     *
523
     * @return void
524
     */
525
    public function checkPreUpgrade(string $databaseType)
526
    {
527
        if (!$this->checkMinimumPhpVersion()) {
528
            printf(
529
                '<p class="alert alert-danger">Sorry, but you need PHP %s or later!</p>',
530
                System::VERSION_MINIMUM_PHP
531
            );
532
            System::renderFooter();
533
        }
534
535
        if (!is_readable(PMF_ROOT_DIR.'/inc/data.php') && !is_readable(PMF_ROOT_DIR.'/config/database.php')) {
536
            echo '<p class="alert alert-danger">It seems you never run a version of phpMyFAQ.<br>'.
537
                'Please use the <a href="setup.php">install script</a>.</p>';
538
            System::renderFooter();
539
        }
540
541
        if ('' !== $databaseType) {
542
            $databaseFound = false;
543
            foreach ($this->system->getSupportedDatabases() as $database => $values) {
544
                if ($database === $databaseType) {
545
                    $databaseFound = true;
546
                    break;
547
                }
548
            }
549
            if (!$databaseFound) {
550
                echo '<p class="alert alert-danger">It seems you\'re using an unsupported database version.<br>'.
551
                    'We found '.ucfirst($database).'<br>'.
0 ignored issues
show
Bug introduced by
The variable $database seems to be defined by a foreach iteration on line 543. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
552
                    'Please use the change the database type in <code>config/database.php</code>.</p>';
553
                System::renderFooter();
554
            }
555
        }
556
    }
557
558
    /**
559
     * Checks the minimum required PHP version, defined in System.
560
     *
561
     * @return bool
562
     */
563
    public function checkMinimumPhpVersion()
564
    {
565
        if (version_compare(PHP_VERSION, System::VERSION_MINIMUM_PHP, '<')) {
566
            return false;
567
        }
568
569
        return true;
570
    }
571
572
    /**
573
     * Checks if the file permissions are okay.
574
     */
575
    public function checkFilesystemPermissions()
576
    {
577
        $instanceSetup = new Setup();
578
        $instanceSetup->setRootDir(PMF_ROOT_DIR);
579
580
        $dirs = ['/attachments', '/config', '/data', '/images'];
581
        $failedDirs = $instanceSetup->checkDirs($dirs);
582
        $numDirs = sizeof($failedDirs);
583
584
        if (1 <= $numDirs) {
585
            printf(
586
                '<p class="alert alert-danger">The following %s could not be created or %s not writable:</p><ul>',
587
                (1 < $numDirs) ? 'directories' : 'directory',
588
                (1 < $numDirs) ? 'are' : 'is'
589
            );
590
            foreach ($failedDirs as $dir) {
591
                echo "<li>$dir</li>\n";
592
            }
593
            printf(
594
                '</ul><p class="alert alert-danger">Please create %s manually and/or change access to chmod 775 (or '.
595
                    'greater if necessary).</p>',
596
                (1 < $numDirs) ? 'them' : 'it'
597
            );
598
            System::renderFooter();
599
        }
600
    }
601
602
    /**
603
     * Checks some non critical settings and print some hints.
604
     *
605
     * @todo We should return an array of messages
606
     */
607
    public function checkNoncriticalSettings()
608
    {
609
        if ((@ini_get('safe_mode') == 'On' || @ini_get('safe_mode') === 1)) {
610
            echo '<p class="alert alert-danger">The PHP safe mode is enabled. You may have problems when phpMyFAQ tries to write '.
611
                ' in some directories.</p>';
612
        }
613
        if (!extension_loaded('gd')) {
614
            echo '<p class="alert alert-danger">You don\'t have GD support enabled in your PHP installation. Please enable GD '.
615
                'support in your php.ini file otherwise you can\'t use Captchas for spam protection.</p>';
616
        }
617
        if (!function_exists('imagettftext')) {
618
            echo '<p class="alert alert-danger">You don\'t have Freetype support enabled in the GD extension of your PHP '.
619
                'installation. Please enable Freetype support in GD extension otherwise the Captchas for spam '.
620
                'protection will be quite easy to break.</p>';
621
        }
622
        if (!extension_loaded('curl') || !extension_loaded('openssl')) {
623
            echo '<p class="alert alert-danger">You don\'t have cURL and/or OpenSSL support enabled in your PHP installation. '.
624
                'Please enable cURL and/or OpenSSL support in your php.ini file otherwise you can\'t use the Twitter '.
625
                ' support or Elasticsearch.</p>';
626
        }
627
        if (!extension_loaded('fileinfo')) {
628
            echo '<p class="alert alert-danger">You don\'t have Fileinfo support enabled in your PHP installation. '.
629
                'Please enable Fileinfo support in your php.ini file otherwise you can\'t use our backup/restore '.
630
                'functionality.</p>';
631
        }
632
    }
633
634
    /**
635
     * Checks if we can store data via sessions. If not, e.g. an user can't
636
     * login into the admin section.
637
     *
638
     * @return bool
639
     */
640
    public function checkSessionSettings()
641
    {
642
        return true;
643
    }
644
645
    /**
646
     * Checks if phpMyFAQ database tables are available
647
     * @param Driver $database
648
     * @throws
649
     */
650
    public function checkAvailableDatabaseTables(Driver $database)
651
    {
652
        $query = sprintf(
653
            'SELECT 1 FROM %s%s LIMIT 1',
654
            Db::getTablePrefix(),
655
            'faqconfig'
656
        );
657
        $result = $database->query($query);
658
        if ($database->numRows($result) === 0) {
659
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Table faqconfig not found.</p>\n";
660
            System::renderFooter(true);
661
        }
662
    }
663
664
    /**
665
     * Starts the installation.
666
     *
667
     * @param array $setup
668
     * @throws
669
     */
670
    public function startInstall(array $setup = null)
671
    {
672
        $query = $uninst = $dbSetup = [];
673
674
        // Check table prefix
675
        $dbSetup['dbPrefix'] = Filter::filterInput(INPUT_POST, 'sqltblpre', FILTER_SANITIZE_STRING, '');
676
        if ('' !== $dbSetup['dbPrefix']) {
677
            Db::setTablePrefix($dbSetup['dbPrefix']);
678
        }
679
680
        // Check database entries
681
        $dbSetup['dbType'] = Filter::filterInput(INPUT_POST, 'sql_type', FILTER_SANITIZE_STRING, $setup['dbType']);
682
        if (!is_null($dbSetup['dbType'])) {
683
            $dbSetup['dbType'] = trim($dbSetup['dbType']);
684
            if (!file_exists(PMF_SRC_DIR.'/phpMyFAQ/Instance/Database/'.ucfirst($dbSetup['dbType']).'.php')) {
685
                printf(
686
                    '<p class="alert alert-danger"><strong>Error:</strong> Invalid server type: %s</p>',
687
                    $dbSetup['dbType']
688
                );
689
                System::renderFooter(true);
690
            }
691
        } else {
692
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please select a database type.</p>\n";
693
            System::renderFooter(true);
694
        }
695
696
        $dbSetup['dbServer'] = Filter::filterInput(INPUT_POST, 'sql_server', FILTER_SANITIZE_STRING, '');
697 View Code Duplication
        if (is_null($dbSetup['dbServer']) && !System::isSqlite($dbSetup['dbType'])) {
698
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database server.</p>\n";
699
            System::renderFooter(true);
700
        }
701
702
        $dbSetup['dbUser'] = Filter::filterInput(INPUT_POST, 'sql_user', FILTER_SANITIZE_STRING, '');
703 View Code Duplication
        if (is_null($dbSetup['dbUser']) && !System::isSqlite($dbSetup['dbType'])) {
704
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database username.</p>\n";
705
            System::renderFooter(true);
706
        }
707
708
        $dbSetup['dbPassword'] = Filter::filterInput(INPUT_POST, 'sql_password', FILTER_UNSAFE_RAW, '');
709
        if (is_null($dbSetup['dbPassword']) && !System::isSqlite($dbSetup['dbType'])) {
710
            // Password can be empty...
711
            $dbSetup['dbPassword'] = '';
712
        }
713
714
        $dbSetup['dbDatabaseName'] = Filter::filterInput(INPUT_POST, 'sql_db', FILTER_SANITIZE_STRING);
715 View Code Duplication
        if (is_null($dbSetup['dbDatabaseName']) && !System::isSqlite($dbSetup['dbType'])) {
716
            echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database name.</p>\n";
717
            System::renderFooter(true);
718
        }
719
720
        if (System::isSqlite($dbSetup['dbType'])) {
721
            $dbSetup['dbServer'] = Filter::filterInput(
722
                INPUT_POST,
723
                'sql_sqlitefile',
724
                FILTER_SANITIZE_STRING,
725
                $setup['dbServer']
726
            );
727
            if (is_null($dbSetup['dbServer'])) {
728
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a SQLite database filename.</p>\n";
729
                System::renderFooter(true);
730
            }
731
        }
732
733
        // check database connection
734
        Db::setTablePrefix($dbSetup['dbPrefix']);
735
        $db = Db::factory($dbSetup['dbType']);
736
        try {
737
            $db->connect($dbSetup['dbServer'], $dbSetup['dbUser'], $dbSetup['dbPassword'], $dbSetup['dbDatabaseName']);
738
        } catch (Exception $e) {
739
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $e->getMessage());
740
        }
741
        if (!$db) {
742
            System::renderFooter(true);
743
        }
744
745
        $configuration = new Configuration($db);
746
747
        //
748
        // Check LDAP if enabled
749
        //
750
        $ldapEnabled = Filter::filterInput(INPUT_POST, 'ldap_enabled', FILTER_SANITIZE_STRING);
751
        if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
752
            $ldapSetup = [];
753
754
            // check LDAP entries
755
            $ldapSetup['ldapServer'] = Filter::filterInput(INPUT_POST, 'ldap_server', FILTER_SANITIZE_STRING);
756
            if (is_null($ldapSetup['ldapServer'])) {
757
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP server.</p>\n";
758
                System::renderFooter(true);
759
            }
760
761
            $ldapSetup['ldapPort'] = Filter::filterInput(INPUT_POST, 'ldap_port', FILTER_VALIDATE_INT);
762
            if (is_null($ldapSetup['ldapPort'])) {
763
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP port.</p>\n";
764
                System::renderFooter(true);
765
            }
766
767
            $ldapSetup['ldapBase'] = Filter::filterInput(INPUT_POST, 'ldap_base', FILTER_SANITIZE_STRING);
768
            if (is_null($ldapSetup['ldapBase'])) {
769
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP base search DN.</p>\n";
770
                System::renderFooter(true);
771
            }
772
773
            // LDAP User and LDAP password are optional
774
            $ldapSetup['ldapUser'] = Filter::filterInput(INPUT_POST, 'ldap_user', FILTER_SANITIZE_STRING, '');
775
            $ldapSetup['ldapPassword'] = Filter::filterInput(INPUT_POST, 'ldap_password', FILTER_SANITIZE_STRING, '');
776
777
            // set LDAP Config to prevent DB query
778
            foreach ($this->_mainConfig as $configKey => $configValue) {
779
                if (strpos($configKey, 'ldap.') !== false) {
780
                    $configuration->config[$configKey] = $configValue;
781
                }
782
            }
783
784
            // check LDAP connection
785
            $ldap = new Ldap($configuration);
786
            $ldap->connect(
787
                $ldapSetup['ldapServer'],
788
                $ldapSetup['ldapPort'],
789
                $ldapSetup['ldapBase'],
790
                $ldapSetup['ldapUser'],
791
                $ldapSetup['ldapPassword']
792
            );
793
            if (!$ldap) {
794
                echo '<p class="alert alert-danger"><strong>LDAP Error:</strong> '.$ldap->error()."</p>\n";
795
                System::renderFooter(true);
796
            }
797
        }
798
799
        //
800
        // Check Elasticsearch if enabled
801
        //
802
        $esEnabled = Filter::filterInput(INPUT_POST, 'elasticsearch_enabled', FILTER_SANITIZE_STRING);
803
        if (!is_null($esEnabled)) {
804
            $esSetup = [];
805
            $esHostFilter = [
806
                'elasticsearch_server' => [
807
                    'filter' => FILTER_SANITIZE_STRING,
808
                    'flags' => FILTER_REQUIRE_ARRAY
809
                ]
810
            ];
811
812
            // ES hosts
813
            $esHosts = Filter::filterInputArray(INPUT_POST, $esHostFilter);
814
            if (is_null($esHosts)) {
815
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add at least one Elasticsearch host.</p>\n";
816
                System::renderFooter(true);
817
            }
818
819
            $esSetup['hosts'] = $esHosts['elasticsearch_server'];
820
821
            // ES Index name
822
            $esSetup['index'] = Filter::filterInput(INPUT_POST, 'elasticsearch_index', FILTER_SANITIZE_STRING);
823
            if (is_null($esSetup['index'])) {
824
                echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add an Elasticsearch index name.</p>\n";
825
                System::renderFooter(true);
826
            }
827
828
            $psr4Loader = new ClassLoader();
829
            $psr4Loader->addPsr4('Elasticsearch\\', PMF_SRC_DIR.'/libs/elasticsearch/src/Elasticsearch');
830
            $psr4Loader->addPsr4('GuzzleHttp\\Ring\\', PMF_SRC_DIR.'/libs/guzzlehttp/ringphp/src');
831
            $psr4Loader->addPsr4('Monolog\\', PMF_SRC_DIR.'/libs/monolog/src/Monolog');
832
            $psr4Loader->addPsr4('Psr\\', PMF_SRC_DIR.'/libs/psr/log/Psr');
833
            $psr4Loader->addPsr4('React\\Promise\\', PMF_SRC_DIR.'/libs/react/promise/src');
834
            $psr4Loader->register();
835
836
            // check LDAP connection
837
            $esHosts = array_values($esHosts['elasticsearch_server']);
838
            $esClient = ClientBuilder::create()
839
                ->setHosts($esHosts)
840
                ->build();
841
842
            if (!$esClient) {
843
                echo '<p class="alert alert-danger"><strong>Elasticsearch Error:</strong> No connection.</p>';
844
                System::renderFooter(true);
845
            }
846
        } else {
847
            $esSetup = [];
848
        }
849
850
        // check loginname
851
        $loginname = Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING, $setup['loginname']);
852
        if (is_null($loginname)) {
853
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a loginname for your account.</p>';
854
            System::renderFooter(true);
855
        }
856
857
        // check user entries
858
        $password = Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING, $setup['password']);
859
        if (is_null($password)) {
860
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a password for the your account.</p>';
861
            System::renderFooter(true);
862
        }
863
864
        $password_retyped = Filter::filterInput(
865
            INPUT_POST,
866
            'password_retyped',
867
            FILTER_SANITIZE_STRING,
868
            $setup['password_retyped']
869
        );
870
        if (is_null($password_retyped)) {
871
            echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a retyped password.</p>';
872
            System::renderFooter(true);
873
        }
874
875
        if (strlen($password) <= 5 || strlen($password_retyped) <= 5) {
876
            echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are too short.'.
877
                ' Please set your password and your retyped password with a minimum of 6 characters.</p>';
878
            System::renderFooter(true);
879
        }
880
        if ($password != $password_retyped) {
881
            echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are not equal.'.
882
                ' Please check your password and your retyped password.</p>';
883
            System::renderFooter(true);
884
        }
885
886
        $language = Filter::filterInput(INPUT_POST, 'language', FILTER_SANITIZE_STRING, 'en');
887
        $realname = Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING, '');
888
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL, '');
889
        $permLevel = Filter::filterInput(INPUT_POST, 'permLevel', FILTER_SANITIZE_STRING, 'basic');
890
891
        $rootDir = isset($setup['rootDir']) ? $setup['rootDir'] : PMF_ROOT_DIR;
892
893
        $instanceSetup = new Setup();
894
        $instanceSetup->setRootDir($rootDir);
895
896
        // Write the DB variables in database.php
897
        if (!$instanceSetup->createDatabaseFile($dbSetup)) {
898
            echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/database.php.</p>';
899
            $this->system->cleanInstallation();
900
            System::renderFooter(true);
901
        }
902
903
        // check LDAP is enabled
904
        if (extension_loaded('ldap') && !is_null($ldapEnabled) && count($ldapSetup)) {
905
            if (!$instanceSetup->createLdapFile($ldapSetup, '')) {
906
                echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/ldap.php.</p>';
907
                $this->system->cleanInstallation();
908
                System::renderFooter(true);
909
            }
910
        }
911
912
        // check if Elasticsearch is enabled
913 View Code Duplication
        if (!is_null($esEnabled) && count($esSetup)) {
914
            if (!$instanceSetup->createElasticsearchFile($esSetup, '')) {
915
                echo '<p class="alert alert-danger"><strong>Error:</strong> Setup cannot write to ./config/elasticsearch.php.</p>';
916
                $this->system->cleanInstallation();
917
                System::renderFooter(true);
918
            }
919
        }
920
921
        // connect to the database using config/database.php
922
        require $rootDir.'/config/database.php';
923
        try {
924
            $db = Db::factory($dbSetup['dbType']);
925
        } catch (Exception $exception) {
926
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $exception->getMessage());
927
            $this->system->cleanInstallation();
928
            System::renderFooter(true);
929
        }
930
931
        $db->connect($DB['server'], $DB['user'], $DB['password'], $DB['db']);
0 ignored issues
show
Bug introduced by
The variable $DB does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
932
        if (!$db) {
933
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $db->error());
934
            $this->system->cleanInstallation();
935
            System::renderFooter(true);
936
        }
937
        try {
938
            $databaseInstaller = Database::factory($configuration, $dbSetup['dbType']);
939
        } catch (Exception $exception) {
940
            printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $exception->getMessage());
941
            $this->system->cleanInstallation();
942
            System::renderFooter(true);
943
        }
944
945
        $databaseInstaller->createTables($dbSetup['dbPrefix']);
946
947
        $stopwords = new Stopwords($configuration);
948
        $stopwords->executeInsertQueries($dbSetup['dbPrefix']);
949
950
        $this->system->setDatabase($db);
951
952
        // Erase any table before starting creating the required ones
953
        if (!System::isSqlite($dbSetup['dbType'])) {
954
            $this->system->dropTables($uninst);
955
        }
956
957
        // Start creating the required tables
958
        $count = 0;
959
        foreach ($query as $executeQuery) {
960
            $result = @$db->query($executeQuery);
961
            if (!$result) {
962
                echo '<p class="alert alert-danger"><strong>Error:</strong> Please install your version of phpMyFAQ once again or send
963
            us a <a href=\"https://www.phpmyfaq.de\" target=\"_blank\">bug report</a>.</p>';
964
                printf('<p class="alert alert-danger"><strong>DB error:</strong> %s</p>', $db->error());
965
                printf('<code>%s</code>', htmlentities($executeQuery));
966
                $this->system->dropTables($uninst);
967
                $this->system->cleanInstallation();
968
                System::renderFooter(true);
969
            }
970
            usleep(1000);
971
            ++$count;
972
            if (!($count%10)) {
973
                echo '| ';
974
            }
975
        }
976
977
        $link = new Link(null, $configuration);
978
979
        // add main configuration, add personal settings
980
        $this->_mainConfig['main.metaPublisher'] = $realname;
981
        $this->_mainConfig['main.administrationMail'] = $email;
982
        $this->_mainConfig['main.language'] = $language;
983
        $this->_mainConfig['security.permLevel'] = $permLevel;
984
985
        foreach ($this->_mainConfig as $name => $value) {
986
            $configuration->add($name, $value);
987
        }
988
989
        $configuration->update(['main.referenceURL' => $link->getSystemUri('/setup/index.php')]);
990
        $configuration->add('security.salt', md5($configuration->getDefaultUrl()));
991
992
        // add admin account and rights
993
        $admin = new User($configuration);
994 View Code Duplication
        if (!$admin->createUser($loginname, $password, null, 1)) {
995
            printf(
996
                '<p class="alert alert-danger"><strong>Fatal installation error:</strong><br>'.
997
                "Couldn't create the admin user: %s</p>\n",
998
                $admin->error()
999
            );
1000
            $this->system->cleanInstallation();
1001
            System::renderFooter(true);
1002
        }
1003
        $admin->setStatus('protected');
1004
        $adminData = [
1005
            'display_name' => $realname,
1006
            'email' => $email,
1007
        ];
1008
        $admin->setUserData($adminData);
1009
1010
        // add default rights
1011
        foreach ($this->mainRights as $right) {
1012
            $admin->perm->grantUserRight(1, $admin->perm->addRight($right));
1013
        }
1014
1015
        // Add anonymous user account
1016
        $instanceSetup->createAnonymousUser($configuration);
1017
1018
        // Add master instance
1019
        $instanceData = [
1020
            'url' => $link->getSystemUri($_SERVER['SCRIPT_NAME']),
1021
            'instance' => $link->getSystemRelativeUri('setup/index.php'),
1022
            'comment' => 'phpMyFAQ '.System::getVersion(),
1023
        ];
1024
        $faqInstance = new Instance($configuration);
1025
        $faqInstance->addInstance($instanceData);
1026
1027
        $faqInstanceMaster = new Master($configuration);
1028
        $faqInstanceMaster->createMaster($faqInstance);
1029
1030
        // connect to Elasticsearch if enabled
1031
        if (!is_null($esEnabled) && is_file($rootDir.'/config/elasticsearch.php')) {
1032
            require $rootDir.'/config/elasticsearch.php';
1033
1034
            $configuration->setElasticsearchConfig($PMF_ES);
0 ignored issues
show
Bug introduced by
The variable $PMF_ES does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1035
1036
            $esClient = ClientBuilder::create()
1037
                ->setHosts($PMF_ES['hosts'])
1038
                ->build();
1039
1040
            $configuration->setElasticsearch($esClient);
1041
1042
            $faqInstanceElasticsearch = new Elasticsearch($configuration);
1043
            $faqInstanceElasticsearch->createIndex();
1044
        }
1045
    }
1046
1047
    /**
1048
     * Cleanup all files after an installation.
1049
     *
1050
     * @return void
1051
     */
1052
    public function cleanUpFiles()
1053
    {
1054
        if (!DEBUG) {
1055
            // Remove 'index.php' file
1056
            if (@unlink(dirname($_SERVER['PATH_TRANSLATED']).'/index.php')) {
1057
                echo "<p class=\"alert alert-success\">The file <em>./setup/index.php</em> was deleted automatically.</p>\n";
1058
            } else {
1059
                echo "<p class=\"alert alert-danger\">Please delete the file <em>./setup/index.php</em> manually.</p>\n";
1060
            }
1061
        }
1062
1063
    }
1064
}
1065