]>
Commit | Line | Data |
---|---|---|
1 | <?php | |
2 | ||
3 | class file_db | |
4 | { | |
5 | public $name = "FileDB"; | |
6 | public $author = "Syzop"; | |
7 | public $version = "1.0"; | |
8 | public $description = "File-based database backend"; | |
9 | public $email = "syzop@vulnscan.org"; | |
10 | ||
11 | function __construct() | |
12 | { | |
13 | Hook::func(HOOKTYPE_USER_LOOKUP, 'file_db::get_user'); | |
14 | Hook::func(HOOKTYPE_USERMETA_ADD, 'file_db::add_usermeta'); | |
15 | Hook::func(HOOKTYPE_USERMETA_DEL, 'file_db::del_usermeta'); | |
16 | Hook::func(HOOKTYPE_USERMETA_GET, 'file_db::get_usermeta'); | |
17 | Hook::func(HOOKTYPE_USER_CREATE, 'file_db::user_create'); | |
18 | Hook::func(HOOKTYPE_GET_USER_LIST, 'file_db::get_user_list'); | |
19 | Hook::func(HOOKTYPE_USER_DELETE, 'file_db::user_delete'); | |
20 | Hook::func(HOOKTYPE_EDIT_USER, 'file_db::edit_core'); | |
21 | Hook::func(HOOKTYPE_PRE_OVERVIEW_CARD, 'file_db::add_pre_overview_card'); | |
22 | AuthModLoaded::$status = 1; | |
23 | ||
24 | file_db::read_db(); | |
25 | ||
26 | if (defined('DEFAULT_USER')) // we've got a default account | |
27 | { | |
28 | $lkup = new PanelUser(DEFAULT_USER['username']); | |
29 | ||
30 | if (!$lkup->id) // doesn't exist, add it with full privileges | |
31 | { | |
32 | $user = []; | |
33 | $user['user_name'] = DEFAULT_USER['username']; | |
34 | $user['user_pass'] = DEFAULT_USER['password']; | |
35 | $user['err'] = ""; | |
36 | create_new_user($user); | |
37 | } | |
38 | $lkup = new PanelUser(DEFAULT_USER['username']); | |
39 | if (!user_can($lkup, PERMISSION_MANAGE_USERS)) | |
40 | $lkup->add_permission(PERMISSION_MANAGE_USERS); | |
41 | } | |
42 | } | |
43 | ||
44 | public static function add_pre_overview_card($empty) | |
45 | { | |
46 | if (defined('DEFAULT_USER')) | |
47 | Message::Fail("Warning: DEFAULT_USER is set in config.php. You should remove that item now, as it is only used during installation."); | |
48 | } | |
49 | ||
50 | public static function get_user_helper($item) | |
51 | { | |
52 | $obj = (object) []; | |
53 | $obj->id = $item["id"]; | |
54 | $obj->username = $item["username"]; | |
55 | $obj->passhash = $item["password"]; | |
56 | $obj->first_name = $item["first_name"]; | |
57 | $obj->last_name = $item["last_name"]; | |
58 | $obj->created = $item["created"]; | |
59 | $obj->bio = $item["bio"]; | |
60 | $obj->email = $item["email"]; | |
61 | $obj->user_meta = (new PanelUser_Meta($obj->id))->list; | |
62 | return $obj; | |
63 | } | |
64 | ||
65 | public static function uid_to_username($id) | |
66 | { | |
67 | GLOBAL $db; | |
68 | foreach($db["users"] as $user=>$details) | |
69 | if ($details["id"] === $id) | |
70 | return $details["username"]; | |
71 | return null; | |
72 | } | |
73 | ||
74 | /* We convert $u with a full user as an object ;D*/ | |
75 | public static function get_user(&$u) | |
76 | { | |
77 | GLOBAL $db; | |
78 | ||
79 | $id = $u['id']; | |
80 | $name = $u['name']; | |
81 | ||
82 | $obj = (object) []; | |
83 | if ($id) | |
84 | { | |
85 | foreach($db["users"] as $user=>$details) | |
86 | if ($details["id"] === $id) | |
87 | $obj = file_db::get_user_helper($details); | |
88 | } | |
89 | if (isset($db["users"][$name])) | |
90 | { | |
91 | $obj = file_db::get_user_helper($db["users"][$name]); | |
92 | } | |
93 | $u['object'] = $obj; | |
94 | return $obj; | |
95 | } | |
96 | ||
97 | public static function get_usermeta(&$u) | |
98 | { | |
99 | GLOBAL $db; | |
100 | ||
101 | $uid = $u['id']; | |
102 | ||
103 | $username = file_db::uid_to_username($uid); | |
104 | if (!$username) | |
105 | die("User not found: $uid\n"); // return false; /* User does not exist */ | |
106 | ||
107 | $u['meta'] = $db["users"][$username]['meta']; | |
108 | } | |
109 | ||
110 | public static function add_usermeta(&$meta) | |
111 | { | |
112 | GLOBAL $db; | |
113 | ||
114 | $meta = $meta['meta']; | |
115 | $uid = $meta['id']; | |
116 | $key = $meta['key']; | |
117 | $value = $meta['value']; | |
118 | ||
119 | file_db::read_db(); | |
120 | $username = file_db::uid_to_username($uid); | |
121 | if (!$username) | |
122 | return false; /* User does not exist */ | |
123 | ||
124 | /* And update */ | |
125 | $db["users"][$username]["meta"][$key] = $value; | |
126 | file_db::write_db(); | |
127 | return true; | |
128 | } | |
129 | ||
130 | public static function del_usermeta(&$meta) | |
131 | { | |
132 | GLOBAL $db; | |
133 | ||
134 | $meta = $meta['meta']; | |
135 | $uid = $meta['id']; | |
136 | $key = $meta['key']; | |
137 | ||
138 | file_db::read_db(); | |
139 | $username = file_db::uid_to_username($uid); | |
140 | if (!$username) | |
141 | return false; /* User does not exist */ | |
142 | ||
143 | /* And delete */ | |
144 | unset($db["users"][$username]["meta"][$key]); | |
145 | ||
146 | file_db::write_db(); | |
147 | return true; | |
148 | } | |
149 | ||
150 | public static function minimal_db() | |
151 | { | |
152 | GLOBAL $db; | |
153 | /* Add at least the general arrays: */ | |
154 | if (!isset($db["users"])) | |
155 | $db["users"] = []; | |
156 | if (!isset($db["settings"])) | |
157 | $db["settings"] = []; | |
158 | /* Initialize more if we ever add more... */ | |
159 | } | |
160 | public static function read_db() | |
161 | { | |
162 | GLOBAL $db; | |
163 | $db_filename = UPATH.'/data/database.php'; | |
164 | @include($db_filename); | |
165 | file_db::minimal_db(); | |
166 | } | |
167 | ||
168 | /* Delete the database -- only called during setup AFTER confirmation! */ | |
169 | public static function delete_db() | |
170 | { | |
171 | GLOBAL $db; | |
172 | $db = []; | |
173 | file_db::minimal_db(); | |
174 | file_db::write_db(true); | |
175 | } | |
176 | ||
177 | public static function write_db($force = false) | |
178 | { | |
179 | GLOBAL $db; | |
180 | /* Refuse to write empty db (or nearly empty) */ | |
181 | if (empty($db) || (empty($db["users"]) && empty($db["settings"])) && !$force) | |
182 | return; | |
183 | ||
184 | $db_filename = UPATH.'/data/database.php'; | |
185 | $tmpfile = UPATH.'/data/database.tmp.'.bin2hex(random_bytes(8)).'.php'; // hmm todo optional location? :D | |
186 | $fd = fopen($tmpfile, "w"); | |
187 | if (!$fd) | |
188 | die("Could not write to temporary database file $tmpfile.<br>We need write permissions on the data/ directory!<br>"); | |
189 | ||
190 | $str = var_export($db, true); | |
191 | if ($str === null) | |
192 | die("Error while running write_db() -- weird!"); | |
193 | if (!fwrite($fd, "<?php\n". | |
194 | "/* This database file is written automatically by the UnrealIRCd webpanel.\n". | |
195 | " * You are not really supposed to edit it manually.\n". | |
196 | " */\n". | |
197 | '$db = '.$str.";\n")) | |
198 | { | |
199 | die("Error writing to database file $tmpfile (on fwrite).<br>"); | |
200 | } | |
201 | if (!fclose($fd)) | |
202 | die("Error writing to database file $tmpfile (on close).<br>"); | |
203 | /* Now atomically rename the file */ | |
204 | if (!rename($tmpfile, $db_filename)) | |
205 | die("Could not write (rename) to file ".$db_filename."<br>"); | |
206 | if (function_exists('opcache_invalidate')) | |
207 | opcache_invalidate($db_filename); | |
208 | } | |
209 | ||
210 | public static function user_create(&$u) | |
211 | { | |
212 | GLOBAL $db; | |
213 | ||
214 | $username = $u['user_name']; | |
215 | $first_name = $u['fname'] ?? NULL; | |
216 | $last_name = $u['lname'] ?? NULL; | |
217 | $password = $u['user_pass'] ?? NULL; | |
218 | $user_bio = $u['user_bio'] ?? NULL; | |
219 | $user_email = $u['user_email'] ?? NULL; | |
220 | $created = date("Y-m-d H:i:s"); | |
221 | $id = random_int(1000000,99999999); | |
222 | ||
223 | file_db::read_db(); | |
224 | ||
225 | if (isset($db["users"][$username])) | |
226 | { | |
227 | $u['errmsg'][] = "Could not add user: user already exists"; | |
228 | return; | |
229 | } | |
230 | ||
231 | $db["users"][$username] = [ | |
232 | "id" => $id, | |
233 | "username" => $username, | |
234 | "first_name" => $first_name, | |
235 | "last_name" => $last_name, | |
236 | "password" => $password, | |
237 | "bio" => $user_bio, | |
238 | "email" => $user_email, | |
239 | "created" => $created, | |
240 | "meta" => [], | |
241 | ]; | |
242 | ||
243 | file_db::write_db(); | |
244 | $u['success'] = true; | |
245 | } | |
246 | ||
247 | public static function get_user_list(&$list) | |
248 | { | |
249 | GLOBAL $db; | |
250 | ||
251 | $userlist = []; | |
252 | foreach($db["users"] as $user=>$details) | |
253 | { | |
254 | $userlist[] = new PanelUser(NULL, $details['id']); | |
255 | } | |
256 | if (!empty($userlist)) | |
257 | $list = $userlist; | |
258 | ||
259 | } | |
260 | ||
261 | public static function user_delete(&$u) | |
262 | { | |
263 | GLOBAL $db; | |
264 | ||
265 | file_db::read_db(); | |
266 | $user = $u['user']; | |
267 | $username = $user->username; | |
268 | $deleted = false; | |
269 | if (isset($db["users"][$username])) | |
270 | { | |
271 | unset($db["users"][$username]); | |
272 | $deleted = true; | |
273 | } | |
274 | file_db::write_db(true); | |
275 | ||
276 | if ($deleted) | |
277 | { | |
278 | $u['info'][] = "Successfully deleted user \"$user->username\""; | |
279 | $u['boolint'] = 1; | |
280 | } else { | |
281 | $u['info'][] = "Unknown error"; | |
282 | $u['boolint'] = 0; | |
283 | } | |
284 | } | |
285 | ||
286 | public static function edit_core($arr) | |
287 | { | |
288 | GLOBAL $db; | |
289 | ||
290 | $user = $arr['user']; | |
291 | $username = $user->username; | |
292 | $info = $arr['info']; | |
293 | ||
294 | file_db::read_db(); | |
295 | ||
296 | foreach($info as $key => $val) | |
297 | { | |
298 | $keyname = NULL; | |
299 | if (!$val || !strlen($val) || BadPtr($val)) | |
300 | continue; | |
301 | if (!strcmp($key,"update_fname") && $val != $user->first_name) | |
302 | { | |
303 | $keyname = "first_name"; | |
304 | $property_name = "first name"; | |
305 | } | |
306 | elseif (!strcmp($key,"update_lname") && $val != $user->last_name) | |
307 | { | |
308 | $keyname = "last_name"; | |
309 | $property_name = "last name"; | |
310 | } | |
311 | elseif (!strcmp($key,"update_bio") && $val != $user->bio) | |
312 | { | |
313 | $keyname = "bio"; | |
314 | $property_name = "bio"; | |
315 | } | |
316 | elseif (!strcmp($key,"update_pass") || !strcmp($key,"update_pass_conf")) | |
317 | { | |
318 | $keyname = "password"; | |
319 | $property_name = "password"; | |
320 | } | |
321 | elseif(!strcmp($key,"update_email") && $val != $user->email) | |
322 | { | |
323 | $keyname = "email"; | |
324 | $property_name = "email address"; | |
325 | } | |
326 | ||
327 | if (!$keyname) | |
328 | continue; | |
329 | ||
330 | if (isset($db["users"][$username])) | |
331 | { | |
332 | $db["users"][$username][$keyname] = $val; | |
333 | Message::Success("Successfully updated the $property_name for $user->username"); | |
334 | } else { | |
335 | Message::Fail("Could not update $property_name for $user->username: ".$stmt->errorInfo()[0]." (CODE: ".$stmt->errorCode().")"); | |
336 | } | |
337 | } | |
338 | ||
339 | file_db::write_db(true); | |
340 | } | |
341 | } | |
342 | ||
343 | class DbSettings { | |
344 | public static function get() | |
345 | { | |
346 | GLOBAL $db; | |
347 | ||
348 | if (!isset($db) || empty($db)) | |
349 | file_db::read_db(); | |
350 | ||
351 | return $db["settings"]; | |
352 | } | |
353 | public static function set($key, $val) : bool | |
354 | { | |
355 | GLOBAL $db; | |
356 | ||
357 | file_db::read_db(); | |
358 | $db["settings"][$key] = $val; | |
359 | file_db::write_db(); | |
360 | return true; | |
361 | } | |
362 | } |