Passed
Push — master ( 34b43e...0017b2 )
by Hesham
04:42
created

LumenerController::__call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
namespace Lumener\Controllers;
3
4
use Illuminate\Routing\Controller;
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Artisan;
7
8
class LumenerController extends Controller
9
{
10
    protected $adminer;
11
    protected $adminer_object;
12
    protected $plugins_path;
13
    protected $allowed_dbs;
14
    protected $protected_dbs;
15
    protected $request;
16
17
    public function __construct(Request $request)
18
    {
19
        if (method_exists(\Route::class, 'hasMiddlewareGroup')
20
        && \Route::hasMiddlewareGroup('lumener')) {
21
            $this->middleware('lumener');
22
        }
23
        // LumenerServiceProvider::register holds the middleware register so it does not need addeed manually.
24
        // User-defined middleware is handled during route definition for Lumen
25
        $this->adminer = LUMENER_STORAGE.'/adminer.php';
26
        $this->adminer_object = __DIR__.'/../logic/adminer_object.php';
27
        $this->plugins_path = LUMENER_STORAGE.'/plugins';
28
        $this->request = $request;
29
    }
30
31
    public function __call($method, $params)
32
    {
33
        if (strncasecmp($method, "get", 3) === 0) {
34
            $var = preg_replace_callback('/[A-Z]/', function ($c) {
35
                return '_'.strtolower($c[0]);
36
            }, lcfirst(substr($method, 3)));
37
            return $this->$var;
38
        }
39
    }
40
41
    public function index()
42
    {
43
        if ($this->request->cookie('adminer_logged_out')
44
            && config('lumener.logout_redirect')) {
45
            return redirect(config('lumener.logout_redirect'));
46
        }
47
        if (isset($_POST['logout'])) {
48
            $t = encrypt(time());
49
            $h = "Set-Cookie: adminer_logged_out={$t}; expires=".gmdate(
50
                "D, d M Y H:i:s",
51
                time() + config('lumener.logout_cooldown', 10)
52
            )." GMT; path=".preg_replace('~\?.*~', '', $_SERVER["REQUEST_URI"]);
53
            header($h);
54
        }
55
        if (file_exists($this->adminer)) {
56
            return $this->_runAdminer();
57
        } else {
58
            return '<div style="text-align:center;color: red;
59
                                margin-top: 200px;font-weight:bold;">
60
                      Adminer was NOT found.
61
                      Run <span style="color:lightgreen;background:black;
62
                                       padding: 5px;border: 5px dashed white;">
63
                                       php artisan lumener:update --force</span>
64
                                       to fix any issues.
65
                    </div>
66
            ';
67
        }
68
    }
69
70
    public function update()
71
    {
72
        Artisan::call('lumener:update');
73
        return nl2br(Artisan::output());
74
    }
75
76
    public function getResource()
77
    {
78
        $file = $this->request->get('file');
79
        $path = realpath(LUMENER_STORAGE."/{$file}");
80
        // Prevent risky file fetching
81
        // This check is very important, it's a major security risk to allow
82
        // Fetching files outside the LUMENER_STORAGE directory
83
        if (
84
            $path === false
85
            || strncmp($path, LUMENER_STORAGE, strlen(LUMENER_STORAGE)) !== 0
86
        ) {
87
            abort(403);
88
        }
89
        $type = $this->request->get('type', mime_content_type($path));
90
        return response()->download($path, $file, ["Content-Type"=>$type]);
91
    }
92
93
    public function isDBBlocked($db)
94
    {
95
        return
96
        (
97
            $this->allowed_dbs !== null
98
            && !in_array($db, $this->allowed_dbs)
99
        )
100
        ||
101
        (
102
            $this->protected_dbs !== null
103
            && in_array($db, $this->protected_dbs)
104
        );
105
    }
106
107
    private function _runAdminer()
108
    {
109
        if (!isset($_GET['username']) && !isset($_POST['auth'])
110
            && config('lumener.auto_login')
111
            && !$this->request->cookie('adminer_logged_out')) {
112
            // Skip login screen
113
            $_GET['username'] =
114
                config('lumener.db.username', env("DB_USERNAME"));
115
            $_GET['db'] =
116
                config('lumener.db.database', env("DB_DATABASE"));
117
            // Password is set in the adminer extension
118
        }
119
        // Security Check
120
        $this->allowed_dbs = config('lumener.security.allowed_db');
121
        $this->protected_dbs = config('lumener.security.protected_db');
122
123
        if ((isset($_GET['db']) && $_GET['db']
124
            && $this->isDBBlocked($_GET['db']))
125
        || (isset($_POST['auth']['db']) && $_POST['auth']['db']
126
            && $this->isDBBlocked($_POST['auth']['db']))) {
127
            abort(403);
128
        }
129
130
        $content =
131
            $this->_runGetBuffer([$this->adminer_object, $this->adminer]);
132
133
        if (strpos($content, "<!DOCTYPE html>") === false) {
134
            die($content);
1 ignored issue
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...
135
        }
136
        return $content;
137
    }
138
139
    private function _runGetBuffer($files, $allowed_errors=[E_WARNING])
140
    {
141
        // Require files
142
        ob_implicit_flush(0);
143
        ob_start();
144
        try {
145
            foreach ($files as $file) {
146
                // require because include will not throw the adminer_exit error
147
                require($file);
148
            }
149
        } catch (\ErrorException $e) {
150
            if (!in_array($e->getSeverity(), $allowed_errors)) {
151
                throw $e;
152
            }
153
        }
154
        $content = "";
155
        while ($level = ob_get_clean()) {
156
            $content = $level . $content;
157
        }
158
        return $content;
159
    }
160
}
161