5.php

main 188 lines · 7.2 KB Raw
Alex Alex Commit Initial commit 01/10/2026 09:20
1<?php
2/**
3 * Step 5 - the administrator.
4 *
5 * Creates an account, a character on it, and remembers the account name so the
6 * last step can put it in page_admin_access.
7 *
8 * The account is created the way register.php does it, so the password hash
9 * matches what login.php expects on this engine.
10 */
11
12if (!defined('ZNOTE_INSTALL')) { http_response_code(403); die('Direct access denied.'); }
13
14$engine = (string)install_get('ServerEngine', 'TFS_10');
15$isOthire = ($engine === 'OTHIRE');
16$done = (bool)install_get('admin_done', false);
17
18if ($_SERVER['REQUEST_METHOD'] === 'POST' && !$done) {
19
20 $accountName = trim((string)($_POST['account'] ?? ''));
21 $password = (string)($_POST['password'] ?? '');
22 $password2 = (string)($_POST['password_again'] ?? '');
23 $email = trim((string)($_POST['email'] ?? ''));
24 $character = trim((string)($_POST['character'] ?? ''));
25
26 $problems = array();
27
28 if ($accountName === '' || strlen($accountName) > 30) { $problems[] = 'The account name is required, up to 30 characters.'; }
29 if ($isOthire) {
30 if (!preg_match('/^[0-9]+$/', $accountName)) {
31 $problems[] = 'OTHire account numbers may only contain digits.';
32 }
33 } elseif (!preg_match('/^[A-Za-z0-9]+$/', $accountName)) {
34 $problems[] = 'The account name may only contain letters and numbers. Do not use @ or special characters.';
35 }
36 if (strlen($password) < 6) { $problems[] = 'The password must be at least 6 characters.'; }
37 if (strlen($password) > 29) { $problems[] = 'The password may not be longer than 29 characters.'; }
38 if ($password !== $password2) { $problems[] = 'The passwords do not match.'; }
39 if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { $problems[] = 'A valid e-mail address is required.'; }
40 if ($character === '' || strlen($character) > 20) { $problems[] = 'The character name is required, up to 20 characters.'; }
41 if (!preg_match('/^[A-Za-z ]+$/', $character)) { $problems[] = 'The character name may only contain letters and spaces.'; }
42
43 if ($problems) {
44 install_error(implode('<br>', array_map('ih', $problems)));
45 } else {
46
47 $link = install_connect($connectError);
48
49 if ($link === null) {
50 install_error('Lost the database connection: ' . ih((string)$connectError));
51 } else {
52
53 $esc = static fn(string $v): string => $link->real_escape_string($v);
54
55 // Refuse rather than silently attach to someone else's account.
56 $taken = @$link->query("SELECT `id` FROM `players` WHERE `name` = '" . $esc($character) . "' LIMIT 1");
57 if ($taken !== false && $taken->num_rows > 0) {
58 install_error('A character named <strong>' . ih($character) . '</strong> already exists.');
59 } else {
60
61 $now = time();
62 $hash = sha1($password);
63
64 if ($isOthire) {
65 // OTHire identifies accounts by number, not by name.
66 $accountId = (int)$accountName;
67 @$link->query("INSERT INTO `accounts` (`id`, `password`, `email`) VALUES ({$accountId}, '{$hash}', '" . $esc($email) . "')");
68 } else {
69 $creation = ($engine === 'TFS_10' || $engine === 'TFS_16' || $engine === 'CANARY')
70 ? ", `creation`" : '';
71 $creationValue = $creation !== '' ? ", {$now}" : '';
72
73 @$link->query("INSERT INTO `accounts` (`name`, `password`, `email`{$creation})
74 VALUES ('" . $esc($accountName) . "', '{$hash}', '" . $esc($email) . "'{$creationValue})");
75 $accountId = (int)$link->insert_id;
76 }
77
78 if ($accountId <= 0) {
79 install_error('Could not create the account: ' . ih($link->error));
80 } else {
81
82 @$link->query("INSERT INTO `znote_accounts` (`account_id`, `ip`, `created`, `points`, `active`, `active_email`, `activekey`, `flag`)
83 VALUES ({$accountId}, 0, {$now}, 0, 1, 1, 0, '')");
84
85 // A level 8 knight with the stock starting stats. The point
86 // is to have a character whose name grants panel access;
87 // tune it in game or from Admin Panel > Character Skills.
88 $ok = @$link->query("INSERT INTO `players`
89 (`name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`,
90 `experience`, `maglevel`, `mana`, `manamax`, `town_id`, `cap`, `sex`, `looktype`)
91 VALUES ('" . $esc($character) . "', 1, {$accountId}, 8, 4, 185, 185, 4200, 0, 90, 90, 1, 470, 1, 128)");
92
93 if (!$ok) {
94 install_error('The account was created but the character was not: ' . ih($link->error)
95 . '<br>Your server\'s <code>players</code> table may need columns this insert does not set.');
96 } else {
97 $playerId = (int)$link->insert_id;
98 @$link->query("INSERT INTO `znote_players` (`player_id`, `created`, `hide_char`, `comment`)
99 VALUES ({$playerId}, {$now}, 0, '')");
100
101 install_state(array(
102 'admin_done' => true,
103 'admin_account' => $accountName,
104 'admin_character' => $character,
105 ));
106 install_max_step(6);
107
108 $link->close();
109 header('Location: ' . install_url(6));
110 exit;
111 }
112 }
113 }
114
115 $link->close();
116 }
117 }
118}
119?>
120<h1>Administrator</h1>
121
122<?php if ($done): ?>
123
124 <p class="good">
125 Account <strong><?= ih(install_get('admin_account')) ?></strong> and character
126 <strong><?= ih(install_get('admin_character')) ?></strong> were created. The account
127 is given panel access at the next step.
128 </p>
129 <div class="actions">
130 <a class="btn" href="<?= install_url(6) ?>">Continue</a>
131 </div>
132
133<?php else: ?>
134
135 <p class="lead">
136 An account to log in with, and a character on it. ZnoteX grants admin rights by
137 <em>account name</em>, so the account name below is what unlocks the panel.
138 </p>
139
140 <form method="post">
141 <div class="row">
142 <div class="field">
143 <label class="lbl" for="account"><?= $isOthire ? 'Account number' : 'Account name' ?></label>
144 <input type="text" id="account" name="account" maxlength="30"
145 value="<?= ih(install_get('admin_account')) ?>" required>
146 <?php if ($isOthire): ?>
147 <p class="hint">OTHire identifies accounts by number.</p>
148 <?php else: ?>
149 <p class="hint">Letters and numbers only. Do not use @ or special characters.</p>
150 <?php endif; ?>
151 </div>
152 <div class="field">
153 <label class="lbl" for="email">E-mail</label>
154 <input type="email" id="email" name="email" required>
155 </div>
156 </div>
157
158 <div class="row">
159 <div class="field">
160 <label class="lbl" for="password">Password</label>
161 <input type="password" id="password" name="password" required>
162 <p class="hint">At least 6 characters.</p>
163 </div>
164 <div class="field">
165 <label class="lbl" for="password_again">Password again</label>
166 <input type="password" id="password_again" name="password_again" required>
167 </div>
168 </div>
169
170 <div class="field">
171 <label class="lbl" for="character">Character name</label>
172 <input type="text" id="character" name="character" maxlength="20" required>
173 <p class="hint">Letters and spaces only. Your character in game &mdash; panel access comes from the account name above.</p>
174 </div>
175
176 <div class="info">
177 The character is created as a level 8 knight with the default starting stats. Change it
178 in game, or from <strong>Admin Panel &rarr; Character Skills</strong>, once you are in.
179 </div>
180
181 <div class="actions">
182 <button class="btn" type="submit">Create the administrator</button>
183 <a class="btn ghost" href="<?= install_url(4) ?>">Back</a>
184 </div>
185 </form>
186
187<?php endif; ?>
188
Top