]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/blob - plugins/file_db/file_db.php
46792112303621d3e94f9a1f83d5294c26bb94e8
[irc/unrealircd/unrealircd-webpanel.git] / plugins / file_db / file_db.php
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(&$u)
131 {
132 $uid = $meta['id'];
133 $key = $meta['key'];
134
135 file_db::read_db();
136 $username = file_db::uid_to_username($uid);
137 if (!$username)
138 return false; /* User does not exist */
139
140 /* And delete */
141 unset($db["users"][$username]["meta"][$key]);
142
143 file_db::write_db();
144 return true;
145 }
146
147 public static function minimal_db()
148 {
149 GLOBAL $db;
150 /* Add at least the general arrays: */
151 if (!isset($db["users"]))
152 $db["users"] = [];
153 if (!isset($db["settings"]))
154 $db["settings"] = [];
155 /* Initialize more if we ever add more... */
156 }
157 public static function read_db()
158 {
159 GLOBAL $db;
160 $db_filename = UPATH.'/data/database.php';
161 @include($db_filename);
162 file_db::minimal_db();
163 }
164
165 /* Delete the database -- only called during setup AFTER confirmation! */
166 public static function delete_db()
167 {
168 GLOBAL $db;
169 $db = [];
170 file_db::minimal_db();
171 file_db::write_db(true);
172 }
173
174 public static function write_db($force = false)
175 {
176 GLOBAL $db;
177 /* Refuse to write empty db (or nearly empty) */
178 if (empty($db) || (empty($db["users"]) && empty($db["settings"])) && !$force)
179 return;
180
181 $db_filename = UPATH.'/data/database.php';
182 $tmpfile = UPATH.'/data/database.tmp.'.bin2hex(random_bytes(8)).'.php'; // hmm todo optional location? :D
183 $fd = fopen($tmpfile, "w");
184 if (!$fd)
185 die("Could not write to temporary database file $tmpfile.<br>We need write permissions on the data/ directory!<br>");
186
187 $str = var_export($db, true);
188 if ($str === null)
189 die("Error while running write_db() -- weird!");
190 if (!fwrite($fd, "<?php\n".
191 "/* This database file is written automatically by the UnrealIRCd webpanel.\n".
192 " * You are not really supposed to edit it manually.\n".
193 " */\n".
194 '$db = '.$str.";\n"))
195 {
196 die("Error writing to database file $tmpfile (on fwrite).<br>");
197 }
198 if (!fclose($fd))
199 die("Error writing to database file $tmpfile (on close).<br>");
200 /* Now atomically rename the file */
201 if (!rename($tmpfile, $db_filename))
202 die("Could not write (rename) to file ".$db_filename."<br>");
203 if (function_exists('opcache_invalidate'))
204 opcache_invalidate($db_filename);
205 }
206
207 public static function user_create(&$u)
208 {
209 GLOBAL $db;
210
211 $username = $u['user_name'];
212 $first_name = $u['fname'] ?? NULL;
213 $last_name = $u['lname'] ?? NULL;
214 $password = $u['user_pass'] ?? NULL;
215 $user_bio = $u['user_bio'] ?? NULL;
216 $user_email = $u['user_email'] ?? NULL;
217 $created = date("Y-m-d H:i:s");
218 $id = random_int(1000000,99999999);
219
220 file_db::read_db();
221
222 if (isset($db["users"][$username]))
223 {
224 $u['errmsg'][] = "Could not add user: user already exists";
225 return;
226 }
227
228 $db["users"][$username] = [
229 "id" => $id,
230 "username" => $username,
231 "first_name" => $first_name,
232 "last_name" => $last_name,
233 "password" => $password,
234 "bio" => $user_bio,
235 "email" => $user_email,
236 "created" => $created,
237 "meta" => [],
238 ];
239
240 file_db::write_db();
241 $u['success'] = true;
242 }
243
244 public static function get_user_list(&$list)
245 {
246 GLOBAL $db;
247
248 $userlist = [];
249 foreach($db["users"] as $user=>$details)
250 {
251 $userlist[] = new PanelUser(NULL, $details['id']);
252 }
253 if (!empty($userlist))
254 $list = $userlist;
255
256 }
257
258 public static function user_delete(&$u)
259 {
260 GLOBAL $db;
261
262 file_db::read_db();
263 $user = $u['user'];
264 $username = $user->username;
265 $deleted = false;
266 if (isset($db["users"][$username]))
267 {
268 unset($db["users"][$username]);
269 $deleted = true;
270 }
271 file_db::write_db(true);
272
273 if ($deleted)
274 {
275 $u['info'][] = "Successfully deleted user \"$user->username\"";
276 $u['boolint'] = 1;
277 } else {
278 $u['info'][] = "Unknown error";
279 $u['boolint'] = 0;
280 }
281 }
282
283 public static function edit_core($arr)
284 {
285 GLOBAL $db;
286
287 $user = $arr['user'];
288 $username = $user->username;
289 $info = $arr['info'];
290
291 file_db::read_db();
292
293 foreach($info as $key => $val)
294 {
295 $keyname = NULL;
296 if (!$val || !strlen($val) || BadPtr($val))
297 continue;
298 if (!strcmp($key,"update_fname") && $val != $user->first_name)
299 {
300 $keyname = "first_name";
301 $property_name = "first name";
302 }
303 elseif (!strcmp($key,"update_lname") && $val != $user->last_name)
304 {
305 $keyname = "last_name";
306 $property_name = "last name";
307 }
308 elseif (!strcmp($key,"update_bio") && $val != $user->bio)
309 {
310 $keyname = "bio";
311 $property_name = "bio";
312 }
313 elseif (!strcmp($key,"update_pass") || !strcmp($key,"update_pass_conf"))
314 {
315 $keyname = "password";
316 $property_name = "password";
317 }
318 elseif(!strcmp($key,"update_email") && $val != $user->email)
319 {
320 $keyname = "email";
321 $property_name = "email address";
322 }
323
324 if (!$keyname)
325 continue;
326
327 if (isset($db["users"][$username]))
328 {
329 $db["users"][$username][$keyname] = $val;
330 Message::Success("Successfully updated the $property_name for $user->username");
331 } else {
332 Message::Fail("Could not update $property_name for $user->username: ".$stmt->errorInfo()[0]." (CODE: ".$stmt->errorCode().")");
333 }
334 }
335
336 file_db::write_db(true);
337 }
338 }
339
340 class DbSettings {
341 public static function get()
342 {
343 GLOBAL $db;
344
345 if (!isset($db) || empty($db))
346 file_db::read_db();
347
348 return $db["settings"];
349 }
350 public static function set($key, $val) : bool
351 {
352 GLOBAL $db;
353
354 file_db::read_db();
355 $db["settings"][$key] = $val;
356 file_db::write_db();
357 return true;
358 }
359 }