1<?php
2// TFS 1.0 functions ///
3
4////////END 1.0 ////////
5
6// Fetch Images
7function fetchImages($status) {
8 return db()->fetchAll(
9 "SELECT `id`, `title`, `desc`, `date`, `status`, `image`, `delhash`, `account_id` FROM `znote_images` WHERE `status` = ? ORDER BY `date` DESC;",
10 [(int)$status]
11 );
12}
13
14// Insert image data
15function insertImage($account_id, $title, $desc, $image, $image_delete) {
16 $title = sanitize($title);
17 $desc = sanitize($desc);
18 $image = sanitize($image);
19 $image_delete = sanitize($image_delete);
20 $account_id = (int)$account_id;
21 $time = time();
22
23 // Insert only if image dosn't already exist there
24 $exist = db()->fetchOne("SELECT `id` FROM `znote_images` WHERE `image` = ? LIMIT 1;", [$image]);
25 if ($exist === false) {
26 db()->execute("INSERT INTO `znote_images` (`title`, `desc`, `date`, `status`, `image`, `delhash`, `account_id`) VALUES (?, ?, ?, 1, ?, ?, ?);", [$title, $desc, $time, $image, $image_delete, $account_id]);
27 return true;
28 }
29 return false;
30}
31
32function updateImage($id, $status) {
33 db()->execute(
34 "UPDATE `znote_images` SET `status` = ? WHERE `id` = ?;",
35 [(int)$status, (int)$id]
36 );
37}
38
39// Fetch killers score
40function fetchMurders() {
41 return db()->fetchAll("SELECT `killed_by`, COUNT(`killed_by`) AS `kills` FROM `player_deaths` WHERE `is_player`='1' GROUP BY `killed_by` ORDER BY COUNT(`killed_by`) DESC LIMIT 0, 10;");
42}
43
44// Fetch deaths score
45function fetchLoosers(): array {
46 $array = db()->fetchAll("
47 SELECT
48 `player_id`,
49 (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `name`,
50 COUNT(`player_id`) AS `Deaths`
51 FROM `player_deaths`
52 GROUP BY `player_id`
53 ORDER BY COUNT(`player_id`) DESC
54 LIMIT 10;
55 ");
56
57 if (!is_array($array)) {
58 return [];
59 }
60
61 foreach ($array as &$row) {
62 unset($row['player_id']);
63 }
64
65 return $array;
66}
67
68// Fetch latest deaths
69function fetchLatestDeaths($from = 0, $to = 30) {
70 return db()->fetchAll("SELECT `d`.`level`, `p`.`name` AS `victim`, `d`.`time`, `d`.`is_player`, `d`.`killed_by` FROM `player_deaths` AS `d` INNER JOIN `players` AS `p` ON `d`.`player_id` = `p`.`id` ORDER BY `time` DESC LIMIT ?, ?;", [(int)$from, (int)$to]);
71}
72
73// latest deaths .3 (Based on code from Hauni@otland.net).
74function fetchLatestDeaths_03($rowz = 30, $killers = false) {
75 $countz = 0;
76 if ($rowz === false || $killers === true) $getdeaths = db()->fetchAll("SELECT * FROM player_deaths ORDER BY date DESC;");
77 else $getdeaths = db()->fetchAll("SELECT * FROM `player_deaths` ORDER BY `date` DESC LIMIT 0, ?;", [(int)$rowz]);
78 $data = false;
79 //while ($showdeaths = mysql_fetch_assoc($getdeaths)) {
80 if ($getdeaths !== false) {
81 for ($i = 0; $i < count($getdeaths); $i++) {
82 $pid = $getdeaths[$i]['player_id'];
83 $level = $getdeaths[$i]['level'];
84 $kid = user_get_kid($getdeaths[$i]['id']);
85
86 $killedby = user_name(user_get_killer_id($kid));
87
88 if ($killedby == false) {
89 $killedby = user_get_killer_m_name($kid);
90 $player = 0;
91 } else {
92 $player = 1;
93 }
94 if ($killedby === false) {
95 $player = 2;
96 $killedby = "Deleted player.";
97 }
98 $getname = db()->fetchOne("SELECT `name` FROM `players` WHERE `id` = ? LIMIT 1;", [$pid]);
99 $name = $getname['name'];
100 $row = array();
101 $row['level'] = $level;
102 $row['victim'] = $name;
103 $row['time'] = $getdeaths[$i]['date'];
104 $row['is_player'] = $player;
105 $row['killed_by'] = $killedby;
106 if ($killers) {
107 if ($player == 1) {
108 if ($rowz !== false) {
109 if ($countz < $rowz) {
110 $data[] = $row;
111 $countz++;
112 }
113 } else {
114 $data[] = $row;
115 }
116 }
117 } else $data[] = $row;
118 }
119 }
120 return $data;
121}
122
123// Support list
124function support_list() {
125 $TFS = Config('ServerEngine');
126 if ($TFS == 'TFS_10') $staffs = db()->fetchAll("SELECT `p`.`id`, `a`.`type` as `group_id`, `p`.`name`, `p`.`account_id` FROM `players` AS `p` INNER JOIN `accounts` AS `a` ON `p`.`account_id` = `a`.`id` WHERE `a`.`type` > 1 ORDER BY `p`.`account_id` DESC, `p`.`group_id` ASC, `p`.`level` ASC;");
127 else $staffs = db()->fetchAll("SELECT `a`.`type` as `group_id`, `p`.`name`, `p`.`online`, `p`.`account_id` FROM `players` AS `p` INNER JOIN `accounts` AS `a` ON `a`.`id` = `p`.`account_id` WHERE `a`.`type` > 1 ORDER BY `p`.`account_id` DESC, `p`.`group_id` ASC, `p`.`level` ASC;");
128 if ($staffs !== false) {
129 foreach($staffs as $k => $v) {
130 foreach($staffs as $key => $value) {
131 if($k != $key && $v['account_id'] == $value['account_id']) {
132 unset($staffs[$k]);
133 }
134 }
135 }
136 $staffs = array_values($staffs);
137 if ($TFS == 'TFS_10') {
138 for ($i = 0; $i < count($staffs); $i++) {
139 // Fix online status on TFS 1.0
140 $staffs[$i]['online'] = (isset($staffs[$i]['id']) && user_is_online_10($staffs[$i]['id'])) ? 1 : 0;
141 unset($staffs[$i]['id']);
142 }
143 }
144 }
145 return $staffs;
146}
147
148function support_list03() {
149 $staffs = db()->fetchAll("SELECT `group_id`, `name`, `online`, `account_id` FROM `players` WHERE `group_id` > 1 ORDER BY `group_id` ASC;");
150
151 if ($staffs !== false) {
152 for ($i = 0; $i < count($staffs); $i++) {
153 // $staffs[$i]['']
154 unset($staffs[$i]['account_id']);
155 }
156 }
157 return $staffs;
158}
159
160// NEWS
161function fetchAllNews() {
162 return db()->fetchAll("
163 SELECT
164 `n`.`id`,
165 `n`.`title`,
166 `n`.`text`,
167 `n`.`date`,
168 `p`.`name`
169 FROM `znote_news` AS `n`
170 INNER JOIN `players` AS `p`
171 ON `n`.`pid` = `p`.`id`
172 ORDER BY `n`.`id` DESC;
173 ");
174}
175
176// HOUSES
177function fetchAllHouses_03() {
178 return db()->fetchAll("SELECT * FROM `houses`;");
179}
180
181// TFS Storage value functions (Warning, I think these things are saved in cache,
182// and thus require server to be offline, or affected players to be offline while using)
183
184// Get player storage list
185function getPlayerStorageList($storage, $minValue) {
186 return db()->fetchAll("SELECT `player_id`, `value` FROM `player_storage` WHERE `key` = ? AND `value` >= ? ORDER BY `value` DESC;", [(int)$storage, (int)$minValue]);
187}
188
189// Get global storage value
190function getGlobalStorage($storage) {
191 return db()->fetchOne("SELECT `value` FROM `global_storage` WHERE `key` = ?;", [(int)$storage]);
192}
193
194// Set global storage value
195function setGlobalStorage($storage, $value) {
196 $storage = (int)$storage;
197 $value = (int)$value;
198
199 // If the storage does not exist yet
200 if (getGlobalStorage($storage) === false) {
201 if (engineIsCanary()) {
202 db()->execute("INSERT INTO `global_storage` (`key`, `value`) VALUES (?, ?)", [$storage, $value]);
203 } else {
204 db()->execute("INSERT INTO `global_storage` (`key`, `world_id`, `value`) VALUES (?, 0, ?)", [$storage, $value]);
205 }
206 } else {// If the storage exist
207 db()->execute("UPDATE `global_storage` SET `value` = ? WHERE `key` = ?", [$value, $storage]);
208 }
209}
210
211// Get player storage value.
212function getPlayerStorage($player_id, $storage, $online = false) {
213 if ($online) $online = user_is_online($player_id);
214 if (!$online) {
215 // user is offline (false), we may safely proceed:
216 return db()->fetchOne("SELECT `value` FROM `player_storage` WHERE `key` = ? AND `player_id` = ?;", [(int)$storage, (int)$player_id]);
217 } else return false;
218}
219
220// Set player storage value
221function setPlayerStorage($player_id, $storage, $value) {
222 $storage = (int)$storage;
223 $value = (int)$value;
224 $player_id = (int)$player_id;
225
226 // If the storage does not exist yet
227 if (getPlayerStorage($player_id, $storage) === false) {
228 db()->execute("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES (?, ?, ?)", [$player_id, $storage, $value]);
229 } else {// If the storage exist
230 db()->execute("UPDATE `player_storage` SET `value` = ? WHERE `key` = ? AND `player_id` = ?", [$value, $storage, $player_id]);
231 }
232}
233
234// Is player online
235function user_is_online($player_id) {
236 $status = user_character_data($player_id, 'online');
237 if ($status !== false) {
238 if ($status['online'] == 1) $status = true;
239 else $status = false;
240 }
241 return $status;
242}
243// For TFS 1.0
244function user_is_online_10($player_id) {
245 $status = db()->fetchOne("SELECT `player_id` FROM `players_online` WHERE `player_id` = ? LIMIT 1;", [(int)$player_id]);
246 return !$status ? $status : true;
247}
248
249// Shop
250// Gets a list of tickets and ticket ids
251function shop_delete_row_order($rowid) {
252 $rowid = (int)$rowid;
253 db()->execute("DELETE FROM `znote_shop_orders` WHERE `id` = ?;", [$rowid]);
254}
255
256function shop_update_row_count($rowid, $count) {
257 $rowid = (int)$rowid;
258 $count = (int)$count;
259 db()->execute("UPDATE `znote_shop_orders` SET `count` = ? WHERE `id` = ?;", [$count, $rowid]);
260}
261
262function shop_account_gender_tickets($accid) {
263 $accid = (int)$accid;
264 return db()->fetchAll("SELECT `id`, `count` FROM `znote_shop_orders` WHERE `account_id` = ? AND `type` = 3;", [$accid]);
265}
266
267// GUILDS
268//
269function guild_remove_member($cid) {
270 db()->execute("UPDATE `players` SET `rank_id` = 0, `guildnick` = NULL WHERE `id` = ?", [(int)$cid]);
271}
272function guild_remove_member_10($cid) {
273 db()->execute("DELETE FROM `guild_membership` WHERE `player_id` = ? LIMIT 1;", [(int)$cid]);
274}
275
276// Returns $gid of a guild leader($cid).
277function guild_leader_gid($leader) {
278 $leader = (int)$leader;
279 if (config('ServerEngine') !== 'OTHIRE')
280 $data = db()->fetchOne("SELECT `id` FROM `guilds` WHERE `ownerid` = ?;", [$leader]);
281 else
282 $data = db()->fetchOne("SELECT `id` FROM `guilds` WHERE `owner_id` = ?;", [$leader]);
283 return ($data === false) ? false : $data['id'];
284}
285
286// Returns guild leader(charID) of a guild. (parameter: guild_ID)
287function guild_leader($gid) {
288 $gid = (int)$gid;
289 if (config('ServerEngine') !== 'OTHIRE')
290 $data = db()->fetchOne("SELECT `ownerid` FROM `guilds` WHERE `id` = ?;", [$gid]);
291 else
292 $data = db()->fetchOne("SELECT `owner_id` FROM `guilds` WHERE `id` = ?;", [$gid]);
293 return ($data !== false) ? $data['ownerid'] : false;
294}
295
296// Gets a list of invited players to a particular guild.
297function guild_invite_list($gid) {
298 return db()->fetchAll("SELECT `gi`.`player_id`, `gi`.`guild_id`, `p`.`name` FROM `guild_invites` AS `gi` INNER JOIN `players` AS `p` ON `gi`.`player_id`=`p`.`id` WHERE `gi`.`guild_id` = ?;", [(int)$gid]);
299}
300
301// Search player table on cid for his rank_id, returns rank_id
302function get_character_guild_rank($cid) {
303 $cid = (int)$cid;
304 if (config('ServerEngine') !== 'TFS_10') {
305 $data = db()->fetchOne("SELECT `rank_id` FROM `players` WHERE `id` = ?;", [$cid]);
306 return ($data !== false && $data['rank_id'] > 0) ? $data['rank_id'] : false;
307 } else {
308 $data = db()->fetchOne("SELECT `rank_id` FROM `guild_membership` WHERE `player_id` = ? LIMIT 1;", [$cid]);
309 return ($data !== false) ? $data['rank_id'] : false;
310 }
311}
312
313// Get a player guild rank, using his rank_id
314function get_player_guild_rank($rank_id) {
315 $data = db()->fetchOne("SELECT `name` FROM `guild_ranks` WHERE `id` = ? LIMIT 1;", [(int)$rank_id]);
316 return ($data !== false) ? $data['name'] : false;
317}
318
319// Get a players rank_id, guild_id, rank_level(ID), rank_name(string), using cid(player id)
320function get_player_guild_data($cid) {
321 $cid = (int)$cid;
322 if (config('ServerEngine') !== 'TFS_10') $playerdata = db()->fetchOne("SELECT `rank_id` FROM `players` WHERE `id` = ? LIMIT 1;", [$cid]);
323 else $playerdata = db()->fetchOne("SELECT `rank_id` FROM `guild_membership` WHERE `player_id` = ? LIMIT 1;", [$cid]);
324
325 if ($playerdata !== false) {
326 $rankdata = db()->fetchOne("SELECT `guild_id`, `level` AS `rank_level`, `name` AS `rank_name` FROM `guild_ranks` WHERE `id` = ? LIMIT 1;", [$playerdata['rank_id']]);
327 if ($rankdata !== false) {
328 $rankdata['rank_id'] = $playerdata['rank_id'];
329 return $rankdata;
330 } else return false;
331 } else return false;
332}
333
334// Returns guild name of guild id
335function get_guild_name($gid) {
336 $guild = db()->fetchOne("SELECT `name` FROM `guilds` WHERE `id` = ? LIMIT 1;", [(int)$gid]);
337 if ($guild !== false) return $guild['name'];
338 else return false;
339}
340
341// Returns guild id from name
342function get_guild_id($name) {
343 $data = db()->fetchOne("SELECT `id` FROM `guilds` WHERE `name` = ?;", [$name]);
344 return ($data !== false) ? $data['id'] : false;
345}
346
347// Returns guild data from name
348function get_guild_data($name) {
349 if (config('ServerEngine') !== 'OTHIRE')
350 return db()->fetchOne("SELECT `id`, `name`, `ownerid`, `creationdata`, `motd` FROM `guilds` WHERE `name` = ? LIMIT 1;", [$name]);
351 else
352 return db()->fetchOne("SELECT `id`, `name`, `owner_id`, `creationdate` FROM `guilds` WHERE `name` = ? LIMIT 1;", [$name]);
353}
354
355// Get complete list of guilds
356function get_guilds_list() {
357 if (config('ServerEngine') !== 'OTHIRE')
358 return db()->fetchAll("SELECT `id`, `name`, `creationdata` FROM `guilds` ORDER BY `name`;");
359 else
360 return db()->fetchAll("SELECT `id`, `name`, `creationdate` FROM `guilds` ORDER BY `name`;");
361}
362
363// Get array of player data related to a guild.
364function get_guild_players($gid) {
365 $gid = (int)$gid; // Sanitizing the parameter id
366 if (config('ServerEngine') !== 'TFS_10') return db()->fetchAll("SELECT `p`.`id`, `p`.`rank_id`, `p`.`name`, `p`.`level`, `p`.`guildnick`, `p`.`vocation`, `p`.`online`, `gr`.`name` AS `rank_name`, `gr`.`level` AS `rank_level` FROM `players` AS `p` LEFT JOIN `guild_ranks` AS `gr` ON `gr`.`id` = `p`.`rank_id` WHERE `gr`.`guild_id` = ? ORDER BY `gr`.`id`, `p`.`name`;", [$gid]);
367 else return db()->fetchAll("SELECT `p`.`id`, `p`.`name`, `p`.`level`, `p`.`vocation`, `gm`.`rank_id`, `gm`.`nick` AS `guildnick`, `gr`.`name` AS `rank_name`, `gr`.`level` AS `rank_level` FROM `players` AS `p` LEFT JOIN `guild_membership` AS `gm` ON `gm`.`player_id` = `p`.`id` LEFT JOIN `guild_ranks` AS `gr` ON `gr`.`id` = `gm`.`rank_id` WHERE `gm`.`guild_id` = ? ORDER BY `gm`.`rank_id`, `p`.`name`", [$gid]);
368}
369
370// Get guild level data (avg level, total level, count of players)
371function get_guild_level_data($gid) {
372 $gid = (int)$gid;
373 $data = (config('ServerEngine') !== 'TFS_10') ? db()->fetchAll("SELECT p.level FROM players AS p LEFT JOIN guild_ranks AS gr ON gr.id = p.rank_id WHERE gr.guild_id = ?;", [$gid]) : db()->fetchAll("SELECT p.level FROM players AS p LEFT JOIN guild_membership AS gm ON gm.player_id = p.id WHERE gm.guild_id = ? ORDER BY gm.rank_id, p.name;", [$gid]);
374 $members = 0;
375 $totallevels = 0;
376 if ($data !== false) {
377 foreach ($data as $player) {
378 $members++;
379 $totallevels += $player['level'];
380 }
381 return array('avg' => (int)($totallevels / $members), 'total' => $totallevels, 'players' => $members);
382 } else return false;
383}
384
385//
386// GUILD WAR
387//
388// Returns guild war entry for id
389function get_guild_war($warid) {
390 return db()->fetchOne("SELECT `id`, `guild1`, `guild2`, `name1`, `name2`, `status`, `started`, `ended` FROM `guild_wars` WHERE `id` = ? ORDER BY `started`;", [(int)$warid]);
391}
392
393// TFS 0.3 compatibility
394function get_guild_war03($warid) {
395 $warid = (int)$warid; // Sanitizing the parameter id
396
397 $war = db()->fetchOne("SELECT `id`, `guild_id`, `enemy_id`, `status`, `begin`, `end`
398 FROM `guild_wars` WHERE `id` = ? ORDER BY `begin` DESC LIMIT 0, 30", [$warid]);
399 if ($war !== false) {
400 $war['guild1'] = $war['guild_id'];
401 $war['guild2'] = $war['enemy_id'];
402 $war['name1'] = get_guild_name($war['guild_id']);
403 $war['name2'] = get_guild_name($war['enemy_id']);
404 $war['started'] = $war['begin'];
405 $war['ended'] = $war['end'];
406 }
407 return $war;
408}
409
410// List all war entries
411function get_guild_wars() {
412 return db()->fetchAll("SELECT `id`, `guild1`, `guild2`, `name1`, `name2`, `status`, `started`, `ended` FROM `guild_wars` ORDER BY `started` DESC LIMIT 0, 30");
413}
414
415// Untested. (TFS 0.3 compatibility)
416function get_guild_wars03() {
417 $array = db()->fetchAll("SELECT `id`, `guild_id`, `enemy_id`, `status`, `begin`, `end` FROM `guild_wars` ORDER BY `begin` DESC LIMIT 0, 30");
418 if (!is_array($array)) {
419 return false;
420 }
421
422 for ($i = 0, $c = count($array); $i < $c; $i++) {
423 // Generating TFS 0.2 key values for this 0.3 query for web cross compatibility
424 $array[$i]['guild1'] = $array[$i]['guild_id'];
425 $array[$i]['guild2'] = $array[$i]['enemy_id'];
426 $array[$i]['name1'] = get_guild_name($array[$i]['guild_id']);
427 $array[$i]['name2'] = get_guild_name($array[$i]['enemy_id']);
428 $array[$i]['started'] = $array[$i]['begin'];
429 $array[$i]['ended'] = $array[$i]['end'];
430 }
431 return $array;
432}
433
434// List kill activity in wars.
435function get_war_kills($war_id) {
436 return db()->fetchAll("SELECT `id`, `killer`, `target`, `killerguild`, `targetguild`, `warid`, `time` FROM `guildwar_kills` WHERE `warid` = ? ORDER BY `time` DESC", [(int)$war_id]);
437}
438
439// TFS 0.3 compatibility
440function get_war_kills03($war_id) {
441 return db()->fetchAll("SELECT `id`, `guild_id`, `war_id`, `death_id` FROM `guild_kills` WHERE `war_id` = ? ORDER BY `id` DESC LIMIT 0, 30", [(int)$war_id]);
442}
443
444// Gesior compatibility port TFS .3
445function gesior_sql_death($warid) {
446 return db()->fetchAll('SELECT `pd`.`id`, `pd`.`date`, `gk`.`guild_id` AS `enemy`, `p`.`name`, `pd`.`level` FROM `guild_kills` gk LEFT JOIN `player_deaths` pd ON `gk`.`death_id` = `pd`.`id` LEFT JOIN `players` p ON `pd`.`player_id` = `p`.`id` WHERE `gk`.`war_id` = ? AND `p`.`deleted` = 0 ORDER BY `pd`.`date` DESC', [(int)$warid]);
447}
448function gesior_sql_killer($did) {
449 return db()->fetchAll('SELECT `p`.`name` AS `player_name`, `p`.`deleted` AS `player_exists`, `k`.`war` AS `is_war` FROM `killers` k LEFT JOIN `player_killers` pk ON `k`.`id` = `pk`.`kill_id` LEFT JOIN `players` p ON `p`.`id` = `pk`.`player_id` WHERE `k`.`death_id` = ? ORDER BY `k`.`final_hit` DESC, `k`.`id` ASC', [(int)$did]);
450}
451// end gesior
452// END GUILD WAR
453
454// ADMIN FUNCTIONS
455function set_ingame_position($name, $acctype) {
456 $acctype = (int)$acctype;
457 $name = sanitize($name);
458
459 $acc_id = user_character_account_id($name);
460 $char_id = user_character_id($name);
461
462 $group_id = 1;
463 if ($acctype == 4) {
464 $group_id = 2;
465 } elseif ($acctype >= 5) {
466 $group_id = 3;
467 }
468 db()->execute("UPDATE `accounts` SET `type` = ? WHERE `id` = ?;", [$acctype, $acc_id]);
469 db()->execute("UPDATE `players` SET `group_id` = ? WHERE `id` = ?;", [$group_id, $char_id]);
470}
471
472// .3
473function set_ingame_position03($name, $acctype) {
474 $acctype = (int)$acctype;
475 $name = sanitize($name);
476
477 $acc_id = user_character_account_id($name);
478 $char_id = user_character_id($name);
479
480 $group_id = 2;
481 if ($acctype == 1) {
482 $group_id = 1;
483 }
484 db()->execute("UPDATE `players` SET `group_id` = ? WHERE `id` = ?;", [$acctype, $char_id]);
485}
486
487// Set rule violation.
488// Return true if success, query error die if failed, and false if $config['website_char'] is not recognized.
489
490function set_rule_violation($charname, $typeid, $actionid, $reasonid, $time, $comment) {
491 $charid = user_character_id($charname);
492 $typeid = (int)$typeid;
493 $actionid = (int)$actionid;
494 $reasonid = (int)$reasonid;
495 $time = ($time === null) ? 0 : (int)($time + time());
496
497 if (engineIsTFS16()) {
498 $data = db()->fetchOne("SELECT `account_id`, " . sqlIpSelect('lastip', 'lastip') . " FROM `players` WHERE `id` = ?;", [(int)$charid]);
499 } else {
500 $data = user_character_data($charid, 'account_id', 'lastip');
501 }
502 if (!is_array($data)) $data = array('account_id' => 0, 'lastip' => 0);
503
504 $accountid = $data['account_id'];
505 $charip = $data['lastip'];
506
507 $comment = sanitize($comment);
508
509 // ...
510 $bannedby = config('website_char');
511 if (user_character_exist($bannedby)) {
512 $bannedby = user_character_id($bannedby);
513
514 if (Config('ServerEngine') === 'TFS_02')
515 db()->execute("INSERT INTO `bans` (`type` ,`ip` ,`mask` ,`player` ,`account` ,`time` ,`reason_id` ,`action_id` ,`comment` ,`banned_by`) VALUES (?, ?, 4294967295, ?, ?, ?, ?, ?, ?, ?);", [$typeid, $charip, $charid, $accountid, $time, $reasonid, $actionid, $comment, $bannedby]);
516 elseif (Config('ServerEngine') === 'TFS_03') {
517 $now = time();
518 switch ($typeid) {
519 case 1: // IP ban
520 db()->execute("INSERT INTO `bans` (`type`, `value`, `param`, `active`, `expires`, `added`, `admin_id`, `comment`) VALUES (?, ?, 4294967295, 1, ?, ?, ?, ?);", [$typeid, $charip, $time, $now, $bannedby, $comment]);
521 break;
522
523 case 2: // namelock
524 db()->execute("INSERT INTO `bans` (`type`, `value`, `param`, `active`, `expires`, `added`, `admin_id`, `comment`) VALUES (?, ?, 4294967295, 1, ?, ?, ?, ?);", [$typeid, $charid, $time, $now, $bannedby, $comment]);
525 break;
526
527 case 3: // acc ban
528 db()->execute("INSERT INTO `bans` (`type`, `value`, `param`, `active`, `expires`, `added`, `admin_id`, `comment`) VALUES (?, ?, 4294967295, 1, ?, ?, ?, ?);", [$typeid, $accountid, $time, $now, $bannedby, $comment]);
529 break;
530
531 case 4: // notation
532 db()->execute("INSERT INTO `bans` (`type`, `value`, `param`, `active`, `expires`, `added`, `admin_id`, `comment`) VALUES (?, ?, 4294967295, 1, ?, ?, ?, ?);", [$typeid, $charid, $time, $now, $bannedby, $comment]);
533 break;
534
535 case 5: // deletion
536 db()->execute("INSERT INTO `bans` (`type`, `value`, `param`, `active`, `expires`, `added`, `admin_id`, `comment`) VALUES (?, ?, 4294967295, 1, ?, ?, ?, ?);", [$typeid, $charid, $time, $now, $bannedby, $comment]);
537 break;
538 }
539 }
540 elseif (Config('ServerEngine') === 'TFS_10') {
541 $now = time();
542
543 switch ($typeid) {
544 case 1: // IP ban
545 db()->execute("INSERT INTO `ip_bans` (`ip`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" . sqlIpWrite($charip) . ", ?, ?, ?, ?);", [$comment, $now, $time, $bannedby]);
546 break;
547
548 case 2: // namelock
549 db()->execute("INSERT INTO `player_namelocks` (`player_id`, `reason`, `namelocked_at`, `namelocked_by`) VALUES (?, 'comment', ?, ?);", [$charid, $now, $bannedby]);
550 break;
551
552 case 3: // acc ban
553 db()->execute("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (?, ?, ?, ?, ?);", [$accountid, $comment, $now, $time, $bannedby]);
554 break;
555
556 case 4: // notation
557 data_dump(false, array('status' => false), "Function deprecated. Ban option does not exist in TFS 1.0.");
558 die();
559 break;
560
561 case 5: // deletion
562 data_dump(false, array('status' => false), "Function deprecated. Ban option does not exist in TFS 1.0.");
563 die();
564 break;
565 }
566 }
567
568 return true;
569 } else {
570 return false;
571 }
572}
573
574// -- END admin
575
576// Fetch deathlist
577function user_fetch_deathlist($char_id) {
578 return db()->fetchAll("SELECT * FROM `player_deaths` WHERE `player_id` = ? order by `time` DESC LIMIT 0, 10", [(int)$char_id]);
579}
580
581// TFS .3 compatibility
582function user_fetch_deathlist03($char_id) {
583 $data = db()->fetchAll("SELECT * FROM `player_deaths` WHERE `player_id` = ? order by `date` DESC LIMIT 0, 10", [(int)$char_id]);
584 if ($data !== false) {
585 for ($i = 0; $i < count($data); $i++) {
586 $data[$i]['time'] = $data[$i]['date'];
587 }
588 }
589 return $data;
590}
591
592// same (death id ---> killer id)
593function user_get_kid($did) {
594 $data = db()->fetchOne("SELECT `id` FROM `killers` WHERE `death_id` = ?;", [(int)$did]);
595 return ($data !== false) ? $data['id'] : false;
596}
597// same (killer id ---> player id)
598function user_get_killer_id($kn) {
599 $data = db()->fetchOne("SELECT `player_id` FROM `player_killers` WHERE `kill_id` = ?;", [(int)$kn]);
600 return ($data !== false) ? $data['player_id'] : false;
601}
602// same (killer id ---> monster name)
603function user_get_killer_m_name($mn) {
604 $data = db()->fetchOne("SELECT `name` FROM `environment_killers` WHERE `kill_id` = ?;", [(int)$mn]);
605 return ($data !== false) ? $data['name'] : false;
606}
607
608// Count character deaths. Counts up 10.
609function user_count_deathlist($char_id) {
610 $data = db()->fetchOne("SELECT COUNT(`id`) AS `id` FROM `player_deaths` WHERE `player_id` = ? order by `time` DESC LIMIT 0, 10", [(int)$char_id]);
611 return ($data !== false) ? $data['id'] : false;
612}
613
614// MY ACCOUNT RELATED \\
615function user_update_comment($char_id, $comment) {
616 db()->execute("UPDATE `znote_players` SET `comment` = ? WHERE `player_id` = ?", [$comment, $char_id]);
617}
618
619// Permamently delete character id. (parameter: character id)
620function user_delete_character($char_id) {
621 $char_id = (int)$char_id;
622 db()->execute("DELETE FROM `players` WHERE `id` = ?;", [$char_id]);
623 db()->execute("DELETE FROM `znote_players` WHERE `player_id` = ?;", [$char_id]);
624}
625
626// Delete character with supplied id with a delay.
627function user_delete_character_soft($char_id) {
628 $char_id = (int)$char_id;
629
630 $char_name = user_character_name($char_id);
631 $original_acc_id = user_character_account_id($char_name);
632 if(!user_character_pending_delete($char_name)) {
633 $interval = (string)config('delete_character_interval');
634 if (!preg_match('/^\d+\s+[A-Z]+$/i', $interval)) {
635 $interval = '3 DAY';
636 }
637 db()->execute('INSERT INTO `znote_deleted_characters`(`original_account_id`, `character_name`, `time`, `done`) VALUES(?, ?, (NOW() + INTERVAL ' . $interval . '), 0)', [$original_acc_id, $char_name]);
638 } else
639 return false;
640}
641
642// Check if character will be deleted soon.
643function user_character_pending_delete($char_name) {
644 $result = db()->fetchOne('SELECT `done` FROM `znote_deleted_characters` WHERE `character_name` = ?', [$char_name]);
645 return ($result === false) ? false : !$result['done'];
646}
647
648// Get pending character deletes for supplied account id.
649function user_pending_deletes($acc_id) {
650 return db()->fetchAll('SELECT `id`, `character_name`, `time` FROM `znote_deleted_characters` WHERE `original_account_id` = ? AND `done` = 0', [(int)$acc_id]);
651}
652
653// Parameter: accounts.id returns: An array containing detailed information of every character on the account.
654function user_character_list($account_id) {
655 //$count = user_character_list_count($account_id);
656 $account_id = (int)$account_id;
657
658 $characters = db()->fetchAll("
659 SELECT
660 `p`.`id`,
661 `p`.`name`,
662 `p`.`level`,
663 `p`.`vocation`,
664 `p`.`town_id`,
665 `p`.`lastlogin`,
666 `gm`.`rank_id`,
667 `zp`.`hide_char`,
668 CASE WHEN `po`.`player_id` IS NULL
669 THEN 0
670 ELSE 1
671 END AS `online`
672 FROM `players` AS `p`
673 LEFT JOIN `guild_membership` AS `gm`
674 ON `p`.`id`=`gm`.`player_id`
675 LEFT JOIN `players_online` AS `po`
676 ON `p`.`id`=`po`.`player_id`
677 LEFT JOIN `znote_players` AS `zp`
678 ON `p`.`id`=`zp`.`player_id`
679 WHERE `p`.`account_id` = ?
680 ORDER BY `p`.`level` DESC
681 ", [$account_id]);
682
683 if ($characters !== false) {
684 $count = count($characters);
685 for ($i = 0; $i < $count; $i++) {
686 $characters[$i]['vocation'] = vocation_id_to_name($characters[$i]['vocation']); // Change vocation id to vocation name
687 $characters[$i]['town_id'] = town_id_to_name($characters[$i]['town_id']); // Change town id to town name
688
689 // Make lastlogin human read-able.
690 if ($characters[$i]['lastlogin'] != 0) {
691 $characters[$i]['lastlogin'] = getClock($characters[$i]['lastlogin'], true, false);
692 } else {
693 $characters[$i]['lastlogin'] = 'Never.';
694 }
695
696 $characters[$i]['online'] = online_id_to_name($characters[$i]['online']); // 0 to "offline", 1 to "ONLINE".
697 }
698 }
699
700 return $characters;
701}
702
703// Returns an array containing all(up to 30) player_IDs an account have. (parameter: account_ID).
704function user_character_list_player_id($account_id) {
705 //$count = user_character_list_count($account_id);
706 return db()->fetchAll("SELECT `id` FROM `players` WHERE `account_id` = ? ORDER BY `level` DESC LIMIT 0, 30", [$account_id]);
707}
708
709// Parameter: accounts.id returns: number of characters on the account.
710function user_character_list_count($account_id) {
711 $data = db()->fetchOne("SELECT COUNT(`id`) AS `id` FROM `players` WHERE `account_id` = ?", [$account_id]);
712 return ($data !== false) ? $data['id'] : 0;
713}
714
715// END MY ACCOUNT RELATED
716
717// HIGHSCORE FUNCTIONS \\
718function fetchAllScores($rows, $tfs, $g, $vlist, $v = -1, $flags = false, $outfits = false) {
719 if (config('client') < 780) {
720 $outfits = ($outfits) ? ", `p`.`lookbody` AS `body`, `p`.`lookfeet` AS `feet`, `p`.`lookhead` AS `head`, `p`.`looklegs` AS `legs`, `p`.`looktype` AS `type`" : "";
721 } else {
722 $outfits = ($outfits) ? ", `p`.`lookbody` AS `body`, `p`.`lookfeet` AS `feet`, `p`.`lookhead` AS `head`, `p`.`looklegs` AS `legs`, `p`.`looktype` AS `type`, `p`.`lookaddons` AS `addons`" : "";
723 }
724 // Return scores ordered by type and vocation (if set)
725 $data = array();
726
727 // Add "all" as a simulated vocation in vocation_list to represent all vocations and loop through them.
728 $vocGroups = array(
729 'all' => array()
730 );
731 foreach ($vlist AS $vid => $vdata) {
732 // If this vocation does not have a fromVoc attribute
733 if ($vdata['fromVoc'] === false) {
734 // Add it as a group
735 $vocGroups[(string)$vid] = array();
736 } else {
737 // Add an extended group for both vocations
738 $sharedGroup = (string)$vdata['fromVoc'] . ", " . (string)$vid;
739 $vocGroups[$sharedGroup] = array();
740
741 // Make the fromVoc group a reference to the extended group for both vocations
742 $vocGroups[(string)$vdata['fromVoc']] = $sharedGroup;
743 $vocGroups[(string)$vid] = $sharedGroup;
744 }
745 }
746
747 foreach ($vocGroups as $voc_id => $key_or_arr) {
748
749 $vGrp = $voc_id;
750 // Change to correct vocation group if this vocation id reference a shared vocation group
751 if (!is_array($key_or_arr)) $vGrp = $key_or_arr;
752
753 // If this vocation group is empty (then we need to fill it with highscore SQL Data)
754 if (empty($vocGroups[$vGrp])) {
755
756 // Generate SQL WHERE-clause for vocation if $v is set
757 $v = '';
758 if ($vGrp !== 'all')
759 $v = (strpos($vGrp, ',') !== false) ? 'AND `p`.`vocation` IN ('. $vGrp . ')' : 'AND `p`.`vocation` = \''.intval($vGrp).'\'';
760
761 if ($flags === false) { // In this case we only need to query players table
762 $v = str_replace('`p`.', '', $v);
763 $outfits = str_replace('`p`.', '', $outfits);
764
765 $vocGroups[$vGrp][1] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_club` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_club` DESC LIMIT 0, ?;", [$g, $rows]);
766 $vocGroups[$vGrp][2] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_sword` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_sword` DESC LIMIT 0, ?;", [$g, $rows]);
767 $vocGroups[$vGrp][3] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_axe` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_axe` DESC LIMIT 0, ?;", [$g, $rows]);
768 $vocGroups[$vGrp][4] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_dist` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_dist` DESC LIMIT 0, ?;", [$g, $rows]);
769 $vocGroups[$vGrp][5] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_shielding` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_shielding` DESC LIMIT 0, ?;", [$g, $rows]);
770 $vocGroups[$vGrp][6] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_fishing` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_fishing` DESC LIMIT 0, ?;", [$g, $rows]);
771 $vocGroups[$vGrp][7] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `experience`, `level` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `experience` DESC LIMIT 0, ?;", [$g, $rows]);
772 $vocGroups[$vGrp][8] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `maglevel` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `maglevel` DESC LIMIT 0, ?;", [$g, $rows]);
773 $vocGroups[$vGrp][9] = db()->fetchAll("SELECT `name`, `vocation`, `lastlogout`, `skill_fist` AS `value` $outfits FROM `players` WHERE `group_id` < ? $v ORDER BY `skill_fist` DESC LIMIT 0, ?;", [$g, $rows]);
774
775 } else { // Inner join znote_accounts table to retrieve the flag
776 $vocGroups[$vGrp][1] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_club` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_club` DESC LIMIT 0, ?;", [$g, $rows]);
777 $vocGroups[$vGrp][2] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_sword` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_sword` DESC LIMIT 0, ?;", [$g, $rows]);
778 $vocGroups[$vGrp][3] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_axe` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_axe` DESC LIMIT 0, ?;", [$g, $rows]);
779 $vocGroups[$vGrp][4] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_dist` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_dist` DESC LIMIT 0, ?;", [$g, $rows]);
780 $vocGroups[$vGrp][5] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_shielding` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_shielding` DESC LIMIT 0, ?;", [$g, $rows]);
781 $vocGroups[$vGrp][6] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_fishing` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_fishing` DESC LIMIT 0, ?;", [$g, $rows]);
782 $vocGroups[$vGrp][7] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`experience`, `level` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`experience` DESC LIMIT 0, ?;", [$g, $rows]);
783 $vocGroups[$vGrp][8] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`maglevel` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`maglevel` DESC LIMIT 0, ?;", [$g, $rows]);
784 $vocGroups[$vGrp][9] = db()->fetchAll("SELECT `p`.`name`, `p`.`vocation`, `p`.`lastlogout`, `p`.`skill_fist` AS `value`, `za`.`flag` $outfits FROM `players` AS `p` INNER JOIN `znote_accounts` AS `za` ON `p`.`account_id`=`za`.`account_id` WHERE `p`.`group_id` < ? $v ORDER BY `p`.`skill_fist` DESC LIMIT 0, ?;", [$g, $rows]);
785 }
786 }
787 }
788 return $vocGroups;
789}
790// END HIGHSCORE FUNCTIONS
791
792function user_recover($mode, $edom, $email, $character, $ip) {
793/* -- Lost account function - user_recovery --
794
795 $mode = username/password recovery definition
796 $edom = The remembered value. (if mode is username, edom is players password and vice versa)
797 $email = email address
798 $character = character name
799 $ip = character IP
800*/
801 // Structure verify array data correctly
802 if (config('ServerEngine') !== 'OTHIRE') {
803 if ($mode === 'username') {
804 $verify_data = array(
805 'password' => sha1($edom),
806 'email' => $email
807 );
808 } else {
809 $verify_data = array(
810 'name' => $edom,
811 'email' => $email
812 );
813 }
814 } else {
815 if ($mode === 'username') {
816 $verify_data = array(
817 'password' => sha1($edom),
818 'email' => $email
819 );
820 } else {
821 $verify_data = array(
822 'id' => $edom,
823 'email' => $email
824 );
825 }
826 }
827 // Determine if the submitted information is correct and herit from same account
828 if (user_account_fields_verify_value($verify_data)) {
829
830 // Structure account id fetch method correctly
831 if ($mode == 'username') {
832 $account_id = user_account_id_from_password($verify_data['password']);
833 } else {
834 if (config('ServerEngine') !== 'OTHIRE')
835 $account_id = user_id($verify_data['name']);
836 else
837 $account_id = user_id($verify_data['id']);
838 }
839 // get account id from character name
840 $player_account_id = user_character_account_id($character);
841
842 //Verify that players.account_id matches account.id
843 if ($player_account_id == $account_id) {
844 // verify IP match (IP = accounts.email_new) \\
845 // Fetch IP data
846 $ip_data = user_znote_account_data($account_id, 'ip');
847 if ($ip == $ip_data['ip']) {
848 // IP Match, time to stop verifying SHIT and get on
849 // With giving the visitor his goddamn username/password!
850 if ($mode == 'username') {
851 if (config('ServerEngine') !== 'OTHIRE') {
852 $name_data = user_data($account_id, 'name');
853 echo '<br><p>Your username is:</p> <h3>'. $name_data['name'] .'</h3>';
854 } else {
855 $name_data = user_data($account_id, 'id');
856 echo '<br><p>Your account number is:</p> <h3>'. $name_data['id'] .'</h3>';
857 }
858 } else {
859 $newpass = substr(sha1(random_bytes(32)), 0, 12);
860 echo '<br><p>Your new password is:</p> <h3>'. $newpass .'</h3><p>Remember to login and change it!</p>';
861 user_change_password($account_id, $newpass);
862 }
863 // END?! no, but almost. :)
864 } else { echo'IP does not match.'; }
865 } else { echo'Account data does not match.'; }
866 } else { echo'Account data does not match.'; }
867}
868
869// Get account id from password. This can be inaccurate considering several people may have same password.
870function user_account_id_from_password($password) {
871 $tmp = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `password` = ? LIMIT 1;", [$password]);
872 return $tmp['id'];
873}
874
875// Get account name from id.
876function user_account_id_from_name($id) {
877 $id = (int)$id;
878 if (config('ServerEngine') !== 'OTHIRE') {
879 $result = db()->fetchOne("SELECT `name` FROM `accounts` WHERE `id` = ? LIMIT 1;", [$id]);
880 return $result['name'];
881 } else {
882 $result = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `id` = ? LIMIT 1;", [$id]);
883 return $result['id'];
884 }
885}
886
887// Add additional premium days to account id
888function user_account_add_premdays($accid, $days) {
889 $accid = (int)$accid;
890 $days = (int)$days;
891
892 if ($accid <= 0 || $days <= 0) {
893 return false;
894 }
895
896 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premium_ends_at')) {
897 return db()->execute("
898 UPDATE `accounts`
899 SET `premium_ends_at` = GREATEST(`premium_ends_at`, UNIX_TIMESTAMP()) + (? * 86400)
900 WHERE `id` = ?;
901 ", [$days, $accid]);
902 }
903
904 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'lastday') && znote_column_exists('accounts', 'premdays')) {
905 return db()->execute("
906 UPDATE `accounts`
907 SET `premdays` = GREATEST(0, CEIL((GREATEST(`lastday` + (`premdays` * 86400), UNIX_TIMESTAMP()) - UNIX_TIMESTAMP()) / 86400)) + ?,
908 `lastday` = UNIX_TIMESTAMP()
909 WHERE `id` = ?;
910 ", [$days, $accid]);
911 }
912
913 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premdays')) {
914 return db()->execute("
915 UPDATE `accounts`
916 SET `premdays` = `premdays` + ?
917 WHERE `id` = ?;
918 ", [$days, $accid]);
919 }
920
921 return false;
922}
923
924function user_accounts_add_premdays_all($days) {
925 $days = (int)$days;
926
927 if ($days <= 0) {
928 return false;
929 }
930
931 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premium_ends_at')) {
932 return db()->execute("
933 UPDATE `accounts`
934 SET `premium_ends_at` = GREATEST(`premium_ends_at`, UNIX_TIMESTAMP()) + (? * 86400);
935 ", [$days]);
936 }
937
938 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'lastday') && znote_column_exists('accounts', 'premdays')) {
939 return db()->execute("
940 UPDATE `accounts`
941 SET `premdays` = GREATEST(0, CEIL((GREATEST(`lastday` + (`premdays` * 86400), UNIX_TIMESTAMP()) - UNIX_TIMESTAMP()) / 86400)) + ?,
942 `lastday` = UNIX_TIMESTAMP();
943 ", [$days]);
944 }
945
946 if (function_exists('znote_column_exists') && znote_column_exists('accounts', 'premdays')) {
947 return db()->execute("
948 UPDATE `accounts`
949 SET `premdays` = `premdays` + ?;
950 ", [$days]);
951 }
952
953 return false;
954}
955
956// Name = char name. Changes from male to female & vice versa.
957function user_character_change_gender($name) {
958 $user_id = user_character_id($name);
959 $data = db()->fetchOne("SELECT `sex` FROM `players` WHERE `id` = ?;", [$user_id]);
960 $gender = $data['sex'];
961 $newGender = ($gender == 1) ? 0 : 1;
962 db()->execute("UPDATE `players` SET `sex` = ? WHERE `id` = ?", [$newGender, $user_id]);
963}
964
965// Fetch account ID from player NAME
966function user_character_account_id($character) {
967 $data = db()->fetchOne("SELECT `account_id` FROM `players` WHERE `name` = ?;", [$character]);
968 return ($data !== false) ? $data['account_id'] : false;
969}
970
971// Verify data from accounts table. Parameter is an array of <columnName> - <data to verify>
972// etc array('id' = 4, 'password' = 'test') will verify that logged in user have id 4 and password test.
973function user_account_fields_verify_value($verify_data) {
974 array_walk($verify_data, 'array_sanitize');
975
976 $conditions = array();
977 $params = array();
978
979 foreach ($verify_data as $field => $data) {
980 $conditions[] = '`' . $field . '` = ?';
981 $params[] = $data;
982 }
983 $data = db()->fetchOne("SELECT COUNT(`id`) AS `count` FROM `accounts` WHERE " . implode(' AND ', $conditions) . ";", $params);
984 return ($data !== false && $data['count'] == 1) ? true : false;
985}
986
987// Update accounts, make sure user is logged in first.
988function user_update_account($update_data) {
989 array_walk($update_data, 'array_sanitize');
990
991 $set = array();
992 $params = array();
993
994 foreach ($update_data as $field => $data) {
995 $set[] = '`' . $field . '` = ?';
996 $params[] = $data;
997 }
998
999 $user_id = (int)getSession('user_id');
1000 $params[] = $user_id;
1001
1002 db()->execute("UPDATE `accounts` SET " . implode(', ', $set) . " WHERE `id` = ?;", $params);
1003}
1004
1005// Update znote_accounts table, make sure user is logged in for this. This is used to etc update lastIP
1006function user_update_znote_account($update_data) {
1007 array_walk($update_data, 'array_sanitize');
1008
1009 $set = array();
1010 $params = array();
1011
1012 foreach ($update_data as $field => $data) {
1013 $set[] = '`' . $field . '` = ?';
1014 $params[] = $data;
1015 }
1016
1017 $user_id = (int)getSession('user_id');
1018 $params[] = $user_id;
1019
1020 db()->execute("UPDATE `znote_accounts` SET " . implode(', ', $set) . " WHERE `account_id` = ?;", $params);
1021}
1022
1023function user_password_hash_supported(): bool {
1024 return function_exists('znote_column_exists') && znote_column_exists('znote_accounts', 'password_hash');
1025}
1026
1027function user_set_website_password_hash(int $accountId, string $plainPassword): void {
1028 if (!user_password_hash_supported()) return;
1029 db()->execute("UPDATE `znote_accounts` SET `password_hash` = ? WHERE `account_id` = ?;", [password_hash($plainPassword, PASSWORD_DEFAULT), $accountId]);
1030}
1031
1032function user_verify_login_password(int $accountId, string $plainPassword, string $storedHash, string $salt = ''): bool {
1033 if (user_password_hash_supported()) {
1034 $row = db()->fetchOne("SELECT `password_hash` FROM `znote_accounts` WHERE `account_id` = ? LIMIT 1;", [$accountId]);
1035 if (is_array($row) && !empty($row['password_hash'])) {
1036 return password_verify($plainPassword, (string)$row['password_hash']);
1037 }
1038 }
1039
1040 $legacy = $salt !== '' ? sha1($salt . $plainPassword) : sha1($plainPassword);
1041 if (!hash_equals($storedHash, $legacy)) {
1042 return false;
1043 }
1044
1045 user_set_website_password_hash($accountId, $plainPassword);
1046 return true;
1047}
1048
1049// Change password on account_id (Note: You should verify that he knows the old password before doing this)
1050function user_change_password($user_id, $password) {
1051 $user_id = (int)$user_id;
1052 $plainPassword = (string)$password;
1053
1054 db()->execute("UPDATE `accounts` SET `password` = ? WHERE `id` = ?;", [sha1($plainPassword), $user_id]);
1055 user_set_website_password_hash($user_id, $plainPassword);
1056}
1057// .3 compatibility
1058function user_change_password03($user_id, $password) {
1059 if (config('salt') === true) {
1060 $user_id = (int)$user_id;
1061 $plainPassword = (string)$password;
1062 $salt = user_data($user_id, 'salt');
1063
1064 db()->execute("UPDATE `accounts` SET `password` = ? WHERE `id` = ?;", [sha1($salt['salt'].$plainPassword), $user_id]);
1065 user_set_website_password_hash($user_id, $plainPassword);
1066 } else {
1067 user_change_password($user_id, $password);
1068 }
1069}
1070
1071// Parameter: players.id, value[0 or 1]. Togge hide.
1072function user_character_set_hide($char_id, $value) {
1073 db()->execute("UPDATE `znote_players` SET `hide_char` = ? WHERE `player_id` = ?", [$value, $char_id]);
1074}
1075
1076// CREATE ACCOUNT
1077function user_create_account($register_data, $maildata) {
1078 array_walk($register_data, 'array_sanitize');
1079
1080 if (config('ServerEngine') == 'TFS_03' && config('salt') === true) {
1081 $register_data['salt'] = generate_recovery_key(18);
1082 $register_data['password'] = sha1($register_data['salt'].$register_data['password']);
1083 } else $register_data['password'] = sha1($register_data['password']);
1084
1085 $ip = $register_data['ip'];
1086 $created = $register_data['created'];
1087 $flag = $register_data['flag'];
1088
1089 unset($register_data['ip']);
1090 unset($register_data['created']);
1091 unset($register_data['flag']);
1092
1093 if (config('ServerEngine') == 'TFS_10') $register_data['creation'] = $created;
1094
1095 $fields = '`'. implode('`, `', array_keys($register_data)) .'`';
1096 $placeholders = implode(', ', array_fill(0, count($register_data), '?'));
1097
1098 db()->execute("INSERT INTO `accounts` ($fields) VALUES ($placeholders)", array_values($register_data));
1099
1100 $account_id = (isset($register_data['name'])) ? user_id($register_data['name']) : user_id($register_data['id']);
1101 $activeKey = rand(100000000,999999999);
1102 $active = ($maildata['register']) ? 0 : 1;
1103 db()->execute(
1104 "INSERT INTO `znote_accounts` (`account_id`, `ip`, `created`, `active`, `active_email`, `activekey`, `flag`) VALUES (?, ?, ?, ?, 0, ?, ?)",
1105 [$account_id, $ip, $created, $active, $activeKey, $flag]
1106 );
1107
1108 if ($maildata['register']) {
1109
1110 $thisurl = config('site_url') . "$_SERVER[REQUEST_URI]";
1111 $thisurl .= "?authenticate&u=".$account_id."&k=".$activeKey;
1112
1113 $mailer = new Mail($maildata);
1114
1115 $title = "Please authenticate your account at $_SERVER[HTTP_HOST].";
1116
1117 $body = "<h1>Please click on the following link to authenticate your account:</h1>";
1118 $body .= "<p><a href='$thisurl'>$thisurl</a></p>";
1119 $body .= "<p>Thank you for registering and enjoy your stay at $maildata[fromName].</p>";
1120 $body .= "<hr><p>I am an automatic no-reply e-mail. Any emails sent back to me will be ignored.</p>";
1121
1122 $mailer->sendMail($register_data['email'], $title, $body, $register_data['name']);
1123 }
1124
1125 return (int)$account_id;
1126}
1127
1128// CREATE CHARACTER
1129function user_create_character($character_data) {
1130 array_walk($character_data, 'array_sanitize');
1131 $cnf = fullConfig();
1132
1133 $vocation = (int)$character_data['vocation'];
1134 $playercnf = $cnf['player'];
1135 $base = $playercnf['base'];
1136 $create = $playercnf['create'];
1137 $skills = $create['skills'][$vocation];
1138
1139 $outfit = ($character_data['sex'] == 1) ? $create['male_outfit'] : $create['female_outfit'];
1140
1141 $leveldiff = $create['level'] - $base['level'];
1142
1143 $gains = $cnf['vocations_gain'][$vocation];
1144
1145 $health = $base['health'] + ( $gains['hp'] * $leveldiff );
1146 $mana = $base['mana'] + ( $gains['mp'] * $leveldiff );
1147 $cap = $base['cap'] + ( $gains['cap'] * $leveldiff );
1148
1149 // This is TFS 0.2 compatible import data with Znote AAC mysql schema
1150 if (config('ServerEngine') !== 'OTHIRE') {
1151 $import_data = array(
1152 'name' => $character_data['name'],
1153 'group_id' => 1,
1154 'account_id' => $character_data['account_id'],
1155 'level' => $create['level'],
1156 'vocation' => $vocation,
1157 'health' => $health,
1158 'healthmax' => $health,
1159 'experience' => level_to_experience($create['level']),
1160 'lookbody' => $outfit['body'], /* STARTER OUTFITS */
1161 'lookfeet' => $outfit['feet'],
1162 'lookhead' => $outfit['head'],
1163 'looklegs' => $outfit['legs'],
1164 'looktype' => $outfit['id'],
1165 'lookaddons' => 0,
1166 'maglevel' => $skills['magic'],
1167 'mana' => $mana,
1168 'manamax' => $mana,
1169 'manaspent' => 0,
1170 'soul' => $base['soul'],
1171 'town_id' => $character_data['town_id'],
1172 'posx' => $cnf['default_pos']['x'],
1173 'posy' => $cnf['default_pos']['y'],
1174 'posz' => $cnf['default_pos']['z'],
1175 'conditions' => '',
1176 'cap' => $cap,
1177 'sex' => $character_data['sex'],
1178 'lastlogin' => 0,
1179 'lastip' => $character_data['lastip'],
1180 'save' => 1,
1181 'skull' => 0,
1182 'skulltime' => 0,
1183 'rank_id' => 0,
1184 'guildnick' => '',
1185 'lastlogout' => 0,
1186 'blessings' => 0,
1187 'direction' => 0,
1188 'loss_experience' => 10,
1189 'loss_mana' => 10,
1190 'loss_skills' => 10,
1191 'premend' => 0,
1192 'online' => 0,
1193 'balance' => 0
1194 );
1195 } else {
1196 $import_data = array(
1197 'name' => $character_data['name'],
1198 'group_id' => 1,
1199 'account_id' => $character_data['account_id'],
1200 'level' => $create['level'],
1201 'vocation' => $vocation,
1202 'health' => $health,
1203 'healthmax' => $health,
1204 'experience' => level_to_experience($create['level']),
1205 'lookbody' => $outfit['body'], /* STARTER OUTFITS */
1206 'lookfeet' => $outfit['feet'],
1207 'lookhead' => $outfit['head'],
1208 'looklegs' => $outfit['legs'],
1209 'looktype' => $outfit['id'],
1210 'maglevel' => $skills['magic'],
1211 'mana' => $mana,
1212 'manamax' => $mana,
1213 'manaspent' => 0,
1214 'soul' => $base['soul'],
1215 'town_id' => $character_data['town_id'],
1216 'posx' => $cnf['default_pos']['x'],
1217 'posy' => $cnf['default_pos']['y'],
1218 'posz' => $cnf['default_pos']['z'],
1219 'conditions' => '',
1220 'cap' => $cap,
1221 'sex' => $character_data['sex'],
1222 'lastlogin' => 0,
1223 'lastip' => $character_data['lastip'],
1224 'save' => 1,
1225 'skull_type' => 0,
1226 'skull_time' => 0,
1227 'rank_id' => 0,
1228 'guildnick' => '',
1229 'lastlogout' => 0,
1230 'direction' => 0,
1231 'loss_experience' => 100,
1232 'loss_mana' => 100,
1233 'loss_skills' => 100,
1234 'loss_items' => 10,
1235 'online' => 0,
1236 'balance' => 0
1237 );
1238 }
1239
1240 // Clients below 7.8 don't have outfit addons
1241 if (isset($import_data['lookaddons']) && config('client') < 780) {
1242 unset($import_data['lookaddons']);
1243 }
1244
1245 // TFS 1.0 variations
1246 if ($cnf['ServerEngine'] === 'TFS_10') {
1247 unset($import_data['rank_id']);
1248 unset($import_data['guildnick']);
1249 unset($import_data['direction']);
1250 unset($import_data['loss_experience']);
1251 unset($import_data['loss_mana']);
1252 unset($import_data['loss_skills']);
1253 unset($import_data['premend']);
1254 unset($import_data['online']);
1255
1256 // Skills can be added into the same query on TFS 1.0+
1257 $import_data['skill_fist'] = $skills['fist'];
1258 $import_data['skill_club'] = $skills['club'];
1259 $import_data['skill_sword'] = $skills['sword'];
1260 $import_data['skill_axe'] = $skills['axe'];
1261 $import_data['skill_dist'] = $skills['dist'];
1262 $import_data['skill_shielding'] = $skills['shield'];
1263 $import_data['skill_fishing'] = $skills['fishing'];
1264 }
1265
1266 // If you are no vocation (id 0), use these details instead:
1267 if ($vocation === 0) {
1268 $import_data['level'] = $create['novocation']['level'];
1269 $import_data['experience'] = level_to_experience($create['novocation']['level']);
1270
1271 if ($create['novocation']['forceTown'] === true) {
1272 $import_data['town_id'] = $create['novocation']['townId'];
1273 }
1274 }
1275
1276 $fields = array_keys($import_data); // Fetch select fields
1277
1278 $fields_sql = implode("`, `", $fields); // Convert array into SQL compatible string
1279
1280 $placeholders = array();
1281 $values = array();
1282 foreach ($import_data as $field => $value) {
1283 if ($field === 'lastip') {
1284 $placeholders[] = sqlIpWrite($value);
1285 } else {
1286 $placeholders[] = '?';
1287 $values[] = $value;
1288 }
1289 }
1290 $placeholders_sql = implode(", ", $placeholders);
1291
1292 db()->execute("INSERT INTO `players`(`$fields_sql`) VALUES ($placeholders_sql);", $values);
1293
1294 $created = time();
1295 $charid = user_character_id($import_data['name']);
1296 db()->execute("INSERT INTO `znote_players`(`player_id`, `created`, `hide_char`, `comment`) VALUES (?, ?, 0, '');", [$charid, $created]);
1297
1298 // Player skills TFS 0.2, 0.3/4. (TFS 1.0 is done above character creation)
1299 if ($cnf['ServerEngine'] != 'TFS_10') {
1300 db()->execute("DELETE FROM `player_skills` WHERE `player_id` = ?;", [$charid]);
1301 db()->execute(
1302 "INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (?, 0, ?), (?, 1, ?), (?, 2, ?), (?, 3, ?), (?, 4, ?), (?, 5, ?), (?, 6, ?);",
1303 [
1304 $charid, $skills['fist'],
1305 $charid, $skills['club'],
1306 $charid, $skills['sword'],
1307 $charid, $skills['axe'],
1308 $charid, $skills['dist'],
1309 $charid, $skills['shield'],
1310 $charid, $skills['fishing'],
1311 ]
1312 );
1313 }
1314}
1315
1316// Returns counted value of all players online
1317function user_count_online() {
1318 $online = db()->fetchOne("SELECT COUNT(`player_id`) AS `value` FROM `players_online`;");
1319 return ($online !== false) ? $online['value'] : 0;
1320}
1321
1322// Total number of accounts.
1323if (!function_exists('user_count_accounts')) {
1324 function user_count_accounts() {
1325 $row = db()->fetchOne("SELECT COUNT(`id`) AS `value` FROM `accounts`;");
1326 return ($row !== false) ? $row['value'] : 0;
1327 }
1328}
1329
1330// Total number of characters (players).
1331if (!function_exists('user_count_characters')) {
1332 function user_count_characters() {
1333 $row = db()->fetchOne("SELECT COUNT(`id`) AS `value` FROM `players`;");
1334 return ($row !== false) ? $row['value'] : 0;
1335 }
1336}
1337
1338/* user_character_data (fetches whatever data you want from players table)!
1339 Usage:
1340 $player = user_data(player_ID, 'name', 'level');
1341 echo "Character name: ". $player['name'] .". Level: ". $player['level'];
1342*/
1343function user_character_data($user_id): array|false {
1344 $data = array();
1345 $user_id = (int)$user_id;
1346 $func_num_args = func_num_args();
1347 $func_get_args = func_get_args();
1348 if ($func_num_args > 1) {
1349 unset($func_get_args[0]);
1350 $fields = '`'. implode('`, `', $func_get_args) .'`';
1351 $data = db()->fetchOne("SELECT $fields FROM `players` WHERE `id` = ?;", [$user_id]);
1352 return $data;
1353 }
1354 return false;
1355}
1356
1357// return query data from znote_players table
1358function user_znote_character_data($character_id) {
1359 $data = array();
1360 $charid = (int)$character_id;
1361
1362 $func_num_args = func_num_args();
1363 $func_get_args = func_get_args();
1364
1365 if ($func_num_args > 1) {
1366 unset($func_get_args[0]);
1367
1368 $fields = '`'. implode('`, `', $func_get_args) .'`';
1369 $data = db()->fetchOne("SELECT $fields FROM `znote_players` WHERE `player_id` = ?;", [$charid]);
1370 return $data;
1371 }
1372 return false;
1373}
1374
1375// return query data from znote table
1376// usage: $znoteAAC = user_znote_data('version');
1377// echo $znoteAAC['version'];
1378function user_znote_data() {
1379 $data = array();
1380
1381 $func_num_args = func_num_args();
1382 $func_get_args = func_get_args();
1383
1384 if ($func_num_args > 0) {
1385
1386 $fields = '`'. implode('`, `', $func_get_args) .'`';
1387 return db()->fetchOne("SELECT $fields FROM `znote`;");
1388 } else return false;
1389}
1390
1391// return query data from znote_accounts table
1392// See documentation on user_data. This fetches information from znote_accounts table.
1393function user_znote_account_data($account_id) {
1394 $data = array();
1395 $accid = (int)$account_id;
1396
1397 $func_num_args = func_num_args();
1398 $func_get_args = func_get_args();
1399
1400 if ($func_num_args > 1) {
1401 unset($func_get_args[0]);
1402
1403 $fields = '`'. implode('`, `', $func_get_args) .'`';
1404 return db()->fetchOne("SELECT $fields FROM `znote_accounts` WHERE `account_id` = ? LIMIT 1;", [$accid]);
1405 } else return false;
1406}
1407
1408// return query data from znote_visitors table
1409// See documentation on user_data, but this uses $longip instead.
1410function user_znote_visitor_data($longip) {
1411 $data = array();
1412 $longip = (int)$longip;
1413
1414 $func_num_args = func_num_args();
1415 $func_get_args = func_get_args();
1416
1417 if ($func_num_args > 1) {
1418 unset($func_get_args[0]);
1419
1420 $fields = '`'. implode('`, `', $func_get_args) .'`';
1421 return db()->fetchOne("SELECT $fields FROM `znote_visitors` WHERE `ip` = ?;", [$longip]);
1422 } else return false;
1423}
1424
1425// return query data from znote_visitors_details table
1426// See documentation on user_data, but this uses $longip instead.
1427function user_znote_visitor_details_data($longip) {
1428 $data = array();
1429 $longip = (int)$longip;
1430
1431 $func_num_args = func_num_args();
1432 $func_get_args = func_get_args();
1433
1434 if ($func_num_args > 1) {
1435 unset($func_get_args[0]);
1436
1437 $fields = '`'. implode('`, `', $func_get_args) .'`';
1438 return db()->fetchOne("SELECT $fields FROM `znote_visitors_details` WHERE `ip` = ?;", [$longip]);
1439 } else return false;
1440}
1441
1442/* user_data (fetches whatever data you want from accounts table)!
1443 Usage:
1444 $account = user_data(account_ID, 'password', 'email');
1445 echo $account['email']; //Will then echo out that accounts mail address.
1446*/
1447function user_data($user_id) {
1448 $data = array();
1449 $user_id = (int)$user_id;
1450
1451 $func_num_args = func_num_args();
1452 $func_get_args = func_get_args();
1453
1454 if ($func_num_args > 1) {
1455 unset($func_get_args[0]);
1456
1457 $fields = accountFieldList($func_get_args);
1458 return db()->fetchOne("SELECT $fields FROM `accounts` WHERE `id` = ? LIMIT 1;", [$user_id]);
1459 } else return false;
1460}
1461
1462// Checks if user is activated (Not in use atm)
1463function user_activated($username) {
1464 $username = sanitize($username);
1465 // Deprecated, removed from DB.
1466 return false;
1467}
1468
1469// Checks that username exist in database
1470function user_exist($username) {
1471 $username = (string)$username;
1472 if (config('ServerEngine') !== 'OTHIRE')
1473 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `name` = ?;", [$username]);
1474 else
1475 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `id` = ?;", [$username]);
1476 return ($data !== false) ? true : false;
1477}
1478
1479function user_name($id) { //USERNAME FROM PLAYER ID
1480 $name = db()->fetchOne("SELECT `name` FROM `players` WHERE `id` = ?;", [(int)$id]);
1481 if ($name !== false) return $name['name'];
1482 else return false;
1483}
1484
1485// Checks that character name exist
1486function user_character_exist($username) {
1487 $player = db()->fetchOne("SELECT `id` FROM `players` WHERE `name` = ?;", [$username]);
1488 return ($player !== false) ? $player['id'] : false;
1489}
1490
1491// Checks that this email exist.
1492function user_email_exist($email) {
1493 $email = (string)$email;
1494 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `email` = ?;", [$email]);
1495 return ($data !== false) ? true : false;
1496}
1497
1498// Fetch user account ID from registered email. (this is used by etc lost account)
1499function user_id_from_email($email) {
1500 $email = (string)$email;
1501 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `email` = ?;", [$email]);
1502 return ($data !== false) ? $data['id'] : false;
1503}
1504
1505// Checks that a password exist in the database.
1506function user_password_exist($password) {
1507 $password = sha1($password); // No need to sanitize passwords since we encrypt them.
1508 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `password` = ?;", [$password]);
1509 return ($data !== false) ? true : false;
1510}
1511
1512// Verify that submitted password match stored password in account id
1513function user_password_match($password, $account_id) {
1514 $account_id = (int)$account_id;
1515 $data = db()->fetchOne("SELECT `password` FROM `accounts` WHERE `id` = ?;", [$account_id]);
1516 if ($data === false) return false;
1517 return user_verify_login_password($account_id, (string)$password, (string)$data['password']);
1518}
1519
1520// Get user ID from name
1521function user_id($username) {
1522 $username = (string)$username;
1523 if (config('ServerEngine') !== 'OTHIRE')
1524 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `name` = ? LIMIT 1;", [$username]);
1525 else
1526 $data = db()->fetchOne("SELECT `id` FROM `accounts` WHERE `id` = ? LIMIT 1;", [$username]);
1527 if ($data !== false) return $data['id'];
1528 else return false;
1529}
1530
1531// Get user login ID from username and password
1532function user_login_id($username, $password) {
1533 $username = (string)$username;
1534 if (config('ServerEngine') !== 'OTHIRE')
1535 $data = db()->fetchOne("SELECT `id`, `password` FROM `accounts` WHERE `name` = ? LIMIT 1;", [$username]);
1536 else
1537 $data = db()->fetchOne("SELECT `id`, `password` FROM `accounts` WHERE `id` = ? LIMIT 1;", [$username]);
1538 if ($data === false) return false;
1539 return user_verify_login_password((int)$data['id'], (string)$password, (string)$data['password']) ? (int)$data['id'] : false;
1540}
1541
1542// TFS 0.3+ compatibility.
1543function user_login_id_03($username, $password) {
1544 if (config('salt') === true) {
1545 if (user_exist($username)) {
1546 $user_id = user_id($username);
1547 $username = (string)$username;
1548
1549 $data = db()->fetchOne(
1550 "SELECT `salt`, `id`, `name`, `password` FROM `accounts` WHERE `id` = ?;",
1551 [(int)$user_id]
1552 );
1553 if ($data === false || $data['name'] != $username) return false;
1554 $salt = (string)$data['salt'];
1555 return user_verify_login_password((int)$data['id'], (string)$password, (string)$data['password'], $salt) ? (int)$data['id'] : false;
1556 } else return false;
1557 } else return user_login_id($username, $password);
1558}
1559
1560// Get character ID from character name
1561function user_character_id($charname) {
1562 $char = db()->fetchOne("SELECT `id` FROM `players` WHERE `name` = ?;", [$charname]);
1563 if ($char !== false) return $char['id'];
1564 else return false;
1565}
1566
1567// Get character name from character ID
1568function user_character_name($charID) {
1569 $char = db()->fetchOne('SELECT `name` FROM `players` WHERE `id` = ?', [(int)$charID]);
1570 if ($char !== false) return $char['name'];
1571 else return false;
1572}
1573
1574// Hide user character.
1575function user_character_hide($username) {
1576 $username = user_character_id($username);
1577 $char = db()->fetchOne("SELECT `hide_char` FROM `znote_players` WHERE `player_id` = ?;", [$username]);
1578 if ($char !== false) return $char['hide_char'];
1579 else return false;
1580}
1581
1582// Login with a user. (TFS 0.2)
1583function user_login($username, $password) {
1584 $username = (string)$username;
1585 if (config('ServerEngine') !== 'OTHIRE')
1586 $data = db()->fetchOne("SELECT `id`, `password` FROM `accounts` WHERE `name` = ?;", [$username]);
1587 else
1588 $data = db()->fetchOne("SELECT `id`, `password` FROM `accounts` WHERE `id` = ?;", [$username]);
1589 if ($data === false) return false;
1590 return user_verify_login_password((int)$data['id'], (string)$password, (string)$data['password']) ? (int)$data['id'] : false;
1591}
1592
1593// Login a user with TFS 0.3 compatibility
1594function user_login_03($username, $password) {
1595 if (config('salt') === true) {
1596 $username = (string)$username;
1597 $data = db()->fetchOne(
1598 "SELECT `salt`, `id`, `password`, `name` FROM `accounts` WHERE `name` = ?;",
1599 [$username]
1600 );
1601 if ($data === false || $data['name'] != $username) return false;
1602 $salt = (string)$data['salt'];
1603 return user_verify_login_password((int)$data['id'], (string)$password, (string)$data['password'], $salt) ? (int)$data['id'] : false;
1604 } else return user_login($username, $password);
1605}
1606
1607// Verify that user is logged in
1608function user_logged_in() {
1609 return (getSession('user_id') !== false) ? true : false;
1610}
1611
1612?>
1613