Passed
Push — master ( 7794c5...a89d85 )
by Hesham
22:52
created

LumenerController::_verifyAdminerRequest()   B

Complexity

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