| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | require_once(IA_ROOT_DIR."common/db/db.php"); |
|---|
| 4 | require_once(IA_ROOT_DIR."common/db/smf.php"); |
|---|
| 5 | require_once(IA_ROOT_DIR."common/user.php"); |
|---|
| 6 | require_once(IA_ROOT_DIR."common/cache.php"); |
|---|
| 7 | //require_once(IA_ROOT_DIR."common/db/tags.php"); |
|---|
| 8 | |
|---|
| 9 | // Add an user to the cache, or update if already there. |
|---|
| 10 | // Nothing happens if null is passed. |
|---|
| 11 | // |
|---|
| 12 | // Query functions can use this safely, it will just ignore nulls. |
|---|
| 13 | // Always returns $user. |
|---|
| 14 | function _user_cache_add($user) { |
|---|
| 15 | if (!is_null($user)) { |
|---|
| 16 | log_assert_valid(user_validate($user)); |
|---|
| 17 | mem_cache_set("user-by-name:{$user['username']}", $user); |
|---|
| 18 | mem_cache_set("user-by-id:{$user['id']}", $user); |
|---|
| 19 | } |
|---|
| 20 | return $user; |
|---|
| 21 | } |
|---|
| 22 | |
|---|
| 23 | // Delete an user from the cache. $user must be a valid user. |
|---|
| 24 | function _user_cache_delete($user) { |
|---|
| 25 | log_assert_valid(user_validate($user)); |
|---|
| 26 | mem_cache_delete("user-by-name:{$user['username']}"); |
|---|
| 27 | mem_cache_delete("user-by-id:{$user['id']}"); |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | // Test password in IA1 format. |
|---|
| 31 | function user_test_ia1_password($username, $password) |
|---|
| 32 | { |
|---|
| 33 | // old ia1 users are expected to have the ia1 hashed password |
|---|
| 34 | // as their actual password |
|---|
| 35 | $password = db_query_value(sprintf("SELECT PASSWORD('%s')", |
|---|
| 36 | db_escape($password))); |
|---|
| 37 | // hash password ia2 style |
|---|
| 38 | $password = user_hash_password($password, $username); |
|---|
| 39 | // test |
|---|
| 40 | $query = sprintf("SELECT * |
|---|
| 41 | FROM ia_user |
|---|
| 42 | WHERE username = '%s' AND '%s' = `password`", |
|---|
| 43 | db_escape($username), db_escape($password)); |
|---|
| 44 | |
|---|
| 45 | return _user_cache_add(db_fetch($query)); |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | // Check user's password. |
|---|
| 49 | // Returns user struct or null if user/passwrd is wrong. |
|---|
| 50 | function user_test_password($username, $password) |
|---|
| 51 | { |
|---|
| 52 | // Query database |
|---|
| 53 | $hash = user_hash_password($password, $username); |
|---|
| 54 | $query = sprintf("SELECT * |
|---|
| 55 | FROM ia_user |
|---|
| 56 | WHERE username = %s AND `password` = %s", |
|---|
| 57 | db_quote($username), db_quote($hash)); |
|---|
| 58 | $user = db_fetch($query); |
|---|
| 59 | |
|---|
| 60 | // Store in cache |
|---|
| 61 | return _user_cache_add(db_fetch($query)); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | // Get user by email. Returns valid user or null. |
|---|
| 65 | function user_get_by_email($email) |
|---|
| 66 | { |
|---|
| 67 | // Query database. |
|---|
| 68 | $query = sprintf("SELECT * |
|---|
| 69 | FROM ia_user |
|---|
| 70 | WHERE email = '%s'", |
|---|
| 71 | db_escape($email)); |
|---|
| 72 | $user = db_fetch($query); |
|---|
| 73 | |
|---|
| 74 | // Store in cache if not null. |
|---|
| 75 | return _user_cache_add(db_fetch($query)); |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | // Get user by username. Returns valid user or null. |
|---|
| 79 | function user_get_by_username($user_name) |
|---|
| 80 | { |
|---|
| 81 | // Check the cache. |
|---|
| 82 | if (($res = mem_cache_get("user-by-name:$user_name")) !== false) { |
|---|
| 83 | return $res; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | // Query database. |
|---|
| 87 | $query = sprintf("SELECT * |
|---|
| 88 | FROM ia_user |
|---|
| 89 | WHERE username = '%s'", |
|---|
| 90 | db_escape($user_name)); |
|---|
| 91 | $user = db_fetch($query); |
|---|
| 92 | |
|---|
| 93 | // Keep in cache. |
|---|
| 94 | // If we didn't find an user we store a null in the cache by hand. |
|---|
| 95 | if ($user !== null) { |
|---|
| 96 | return _user_cache_add($user); |
|---|
| 97 | } else { |
|---|
| 98 | mem_cache_set("user-by-name:$user_name", null); |
|---|
| 99 | return null; |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | // Get an user struct by his numeric id. |
|---|
| 104 | // Remarkably similar to user_get_by_username. |
|---|
| 105 | function user_get_by_id($user_id) |
|---|
| 106 | { |
|---|
| 107 | // Check the cache. |
|---|
| 108 | if (($res = mem_cache_get("user-by-id:$user_id")) !== false) { |
|---|
| 109 | return $res; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | // Query database |
|---|
| 113 | $query = sprintf("SELECT * |
|---|
| 114 | FROM ia_user |
|---|
| 115 | WHERE id = %s", |
|---|
| 116 | db_quote($user_id)); |
|---|
| 117 | $user = db_fetch($query); |
|---|
| 118 | |
|---|
| 119 | // Keep in cache |
|---|
| 120 | if ($user !== null) { |
|---|
| 121 | return _user_cache_add($user); |
|---|
| 122 | } else { |
|---|
| 123 | mem_cache_set("user-by-id:$user_id", null); |
|---|
| 124 | return null; |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | // Create a new user. |
|---|
| 130 | // This also creates an user page and SMF user. |
|---|
| 131 | // $user must be a valid user struct, user_id ignored |
|---|
| 132 | // Returns created $user or throws up on error. |
|---|
| 133 | function user_create($user, $remote_ip_info=null) |
|---|
| 134 | { |
|---|
| 135 | log_assert_valid(user_validate($user)); |
|---|
| 136 | |
|---|
| 137 | // DB magic. |
|---|
| 138 | unset($user['id']); |
|---|
| 139 | db_insert("ia_user", $user); |
|---|
| 140 | $user['id'] = db_insert_id(); |
|---|
| 141 | |
|---|
| 142 | // Check db magic |
|---|
| 143 | // FIXME: do we really need this? |
|---|
| 144 | _user_cache_delete($user); |
|---|
| 145 | $new_user = user_get_by_username($user['username']); |
|---|
| 146 | log_assert($new_user, "Failed creating user"); |
|---|
| 147 | |
|---|
| 148 | // Create user page. |
|---|
| 149 | require_once(IA_ROOT_DIR . "common/textblock.php"); |
|---|
| 150 | $replace = array("user_id" => $user['username']); |
|---|
| 151 | textblock_copy_replace("template/newuser", IA_USER_TEXTBLOCK_PREFIX.$user['username'], |
|---|
| 152 | $replace, "public", $new_user['id'], $remote_ip_info); |
|---|
| 153 | |
|---|
| 154 | // Create SMF user |
|---|
| 155 | require_once(IA_ROOT_DIR."common/db/smf.php"); |
|---|
| 156 | $smf_id = smf_create_user($user); |
|---|
| 157 | log_assert($smf_id, "SMF user for {$user['username']} not created."); |
|---|
| 158 | |
|---|
| 159 | // Cache and return |
|---|
| 160 | return _user_cache_add($new_user); |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | // Update user information. |
|---|
| 164 | // $user should be a complete user struct. |
|---|
| 165 | // Uses db_update evilness. |
|---|
| 166 | // Also updates SMF, which is good. |
|---|
| 167 | function user_update($user) |
|---|
| 168 | { |
|---|
| 169 | log_assert_valid(user_validate($user)); |
|---|
| 170 | |
|---|
| 171 | // Update DB |
|---|
| 172 | db_update("ia_user", $user, "id = ".db_quote($user['id'])); |
|---|
| 173 | |
|---|
| 174 | // Update SMF |
|---|
| 175 | smf_update_user($user); |
|---|
| 176 | |
|---|
| 177 | _user_cache_add($user); |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | // Returns array with *all* registered usernames. |
|---|
| 181 | // FIXME: grep and exterminate. |
|---|
| 182 | function user_get_list($all_fields = false) { |
|---|
| 183 | $rows = db_fetch_all("SELECT * FROM `ia_user`"); |
|---|
| 184 | $users = array(); |
|---|
| 185 | foreach ($rows as $row) { |
|---|
| 186 | if ($all_fields) { |
|---|
| 187 | $users[$row['username']] = $row; |
|---|
| 188 | } |
|---|
| 189 | else { |
|---|
| 190 | $users[] = $row['username']; |
|---|
| 191 | } |
|---|
| 192 | } |
|---|
| 193 | return $users; |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | // Get all users. |
|---|
| 197 | // Do not fucking use. |
|---|
| 198 | function user_get_all() { |
|---|
| 199 | return db_fetch_all("SELECT * FROM `ia_user`"); |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | // Counts number of users, cached. |
|---|
| 203 | function user_count() { |
|---|
| 204 | if (($res = mem_cache_get("total-user-count")) !== false) { |
|---|
| 205 | return $res; |
|---|
| 206 | } |
|---|
| 207 | $result = db_query_value("SELECT COUNT(*) FROM ia_user"); |
|---|
| 208 | return mem_cache_set("total-user-count", $result); |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | // Returns array with user submitted tasks. Filter tasks by choosing whether |
|---|
| 212 | // to select failed and solved tasks. |
|---|
| 213 | function user_submitted_tasks($user_id, $solved = true, $failed = true) { |
|---|
| 214 | // construct where |
|---|
| 215 | if ($solved && $failed) { |
|---|
| 216 | // no condition |
|---|
| 217 | $where = ''; |
|---|
| 218 | } |
|---|
| 219 | elseif ($solved) { |
|---|
| 220 | $where = 'AND ia_score_user_round_task.score = 100'; |
|---|
| 221 | } |
|---|
| 222 | elseif ($failed) { |
|---|
| 223 | $where = 'AND ia_score_user_round_task.score < 100'; |
|---|
| 224 | } |
|---|
| 225 | else { |
|---|
| 226 | // This shouldn't happen |
|---|
| 227 | log_error('You can\'t select nothing.'); |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | $query = sprintf("SELECT * |
|---|
| 231 | FROM ia_score_user_round_task |
|---|
| 232 | LEFT JOIN ia_task ON ia_task.id = ia_score_user_round_task.task_id |
|---|
| 233 | WHERE ia_score_user_round_task.user_id = '%s' |
|---|
| 234 | AND ia_score_user_round_task.round_id = 'arhiva' AND NOT ia_task.id IS NULL %s |
|---|
| 235 | GROUP BY ia_task.id |
|---|
| 236 | ORDER BY ia_task.`order`", $user_id, $where); |
|---|
| 237 | |
|---|
| 238 | return db_fetch_all($query); |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | // Returns array with rounds that user has submitted to tasks. |
|---|
| 242 | function user_submitted_rounds($user_id) { |
|---|
| 243 | // FIXME: Find a way to remove the hard-coded "<> 'arhiva'" |
|---|
| 244 | $query = "SELECT * |
|---|
| 245 | FROM ia_score_user_round_task |
|---|
| 246 | LEFT JOIN ia_round ON ia_round.id = ia_score_user_round_task.round_id |
|---|
| 247 | WHERE ia_score_user_round_task.user_id = '%s' |
|---|
| 248 | AND NOT ia_round.id IS NULL AND ia_round.id <> 'arhiva' |
|---|
| 249 | GROUP BY ia_round.id"; |
|---|
| 250 | $query = sprintf($query, $user_id); |
|---|
| 251 | |
|---|
| 252 | return db_fetch_all($query); |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | ?> |
|---|