public function update_profile($id, $info, $section) { $info = Container::get('hooks')->fire('model.profile.update_profile_start', $info, $id, $section); $username_updated = false; $section = Container::get('hooks')->fire('model.profile.update_profile_section', $section, $id, $info); // Validate input depending on section switch ($section) { case 'essentials': $form = array('timezone' => floatval(Input::post('form_timezone')), 'dst' => Input::post('form_dst') ? '1' : '0', 'time_format' => intval(Input::post('form_time_format')), 'date_format' => intval(Input::post('form_date_format'))); // Make sure we got a valid language string if (Input::post('form_language')) { $languages = \FeatherBB\Core\Lister::getLangs(); $form['language'] = Utils::trim(Input::post('form_language')); if (!in_array($form['language'], $languages)) { throw new Error(__('Bad request'), 404); } } if (User::get()->is_admmod) { $form['admin_note'] = Utils::trim(Input::post('admin_note')); // Are we allowed to change usernames? if (User::get()->g_id == ForumEnv::get('FEATHER_ADMIN') || User::get()->g_moderator == '1' && User::get()->g_mod_rename_users == '1') { $form['username'] = Utils::trim(Input::post('req_username')); if ($form['username'] != $info['old_username']) { $errors = ''; $errors = $this->check_username($form['username'], $errors, $id); if (!empty($errors)) { throw new Error($errors[0]); } $username_updated = true; } } // We only allow administrators to update the post count if (User::get()->g_id == ForumEnv::get('FEATHER_ADMIN')) { $form['num_posts'] = intval(Input::post('num_posts')); } } if (ForumSettings::get('o_regs_verify') == '0' || User::get()->is_admmod) { // Validate the email address $form['email'] = strtolower(Utils::trim(Input::post('req_email'))); if (!Container::get('email')->is_valid_email($form['email'])) { throw new Error(__('Invalid email')); } } break; case 'personal': $form = array('realname' => Input::post('form_realname') ? Utils::trim(Input::post('form_realname')) : '', 'url' => Input::post('form_url') ? Utils::trim(Input::post('form_url')) : '', 'location' => Input::post('form_location') ? Utils::trim(Input::post('form_location')) : ''); // Add http:// if the URL doesn't contain it already (while allowing https://, too) if (User::get()->g_post_links == '1') { if ($form['url'] != '') { $url = Url::is_valid($form['url']); if ($url === false) { throw new Error(__('Invalid website URL')); } $form['url'] = $url['url']; } } else { if (!empty($form['url'])) { throw new Error(__('Website not allowed')); } $form['url'] = ''; } if (User::get()->g_id == ForumEnv::get('FEATHER_ADMIN')) { $form['title'] = Utils::trim(Input::post('title')); } elseif (User::get()->g_set_title == '1') { $form['title'] = Utils::trim(Input::post('title')); if ($form['title'] != '') { // A list of words that the title may not contain // If the language is English, there will be some duplicates, but it's not the end of the world $forbidden = array('member', 'moderator', 'administrator', 'banned', 'guest', utf8_strtolower(__('Member')), utf8_strtolower(__('Moderator')), utf8_strtolower(__('Administrator')), utf8_strtolower(__('Banned')), utf8_strtolower(__('Guest'))); if (in_array(utf8_strtolower($form['title']), $forbidden)) { throw new Error(__('Forbidden title')); } } } break; case 'messaging': $form = array('jabber' => Utils::trim(Input::post('form_jabber')), 'icq' => Utils::trim(Input::post('form_icq')), 'msn' => Utils::trim(Input::post('form_msn')), 'aim' => Utils::trim(Input::post('form_aim')), 'yahoo' => Utils::trim(Input::post('form_yahoo'))); // If the ICQ UIN contains anything other than digits it's invalid if (preg_match('%[^0-9]%', $form['icq'])) { throw new Error(__('Bad ICQ')); } break; case 'personality': $form = array(); // Clean up signature from POST if (ForumSettings::get('o_signatures') == '1') { $form['signature'] = Utils::linebreaks(Utils::trim(Input::post('signature'))); // Validate signature if (Utils::strlen($form['signature']) > ForumSettings::get('p_sig_length')) { throw new Error(sprintf(__('Sig too long'), ForumSettings::get('p_sig_length'), Utils::strlen($form['signature']) - ForumSettings::get('p_sig_length'))); } elseif (substr_count($form['signature'], "\n") > ForumSettings::get('p_sig_lines') - 1) { throw new Error(sprintf(__('Sig too many lines'), ForumSettings::get('p_sig_lines'))); } elseif ($form['signature'] && ForumSettings::get('p_sig_all_caps') == '0' && Utils::is_all_uppercase($form['signature']) && !User::get()->is_admmod) { $form['signature'] = utf8_ucwords(utf8_strtolower($form['signature'])); } // Validate BBCode syntax if (ForumSettings::get('p_sig_bbcode') == '1') { $errors = array(); $form['signature'] = Container::get('parser')->preparse_bbcode($form['signature'], $errors, true); if (count($errors) > 0) { throw new Error('<ul><li>' . implode('</li><li>', $errors) . '</li></ul>'); } } } break; case 'display': $form = array('disp_topics' => Utils::trim(Input::post('form_disp_topics')), 'disp_posts' => Utils::trim(Input::post('form_disp_posts')), 'show_smilies' => Input::post('form_show_smilies') ? '1' : '0', 'show_img' => Input::post('form_show_img') ? '1' : '0', 'show_img_sig' => Input::post('form_show_img_sig') ? '1' : '0', 'show_avatars' => Input::post('form_show_avatars') ? '1' : '0', 'show_sig' => Input::post('form_show_sig') ? '1' : '0'); if ($form['disp_topics'] != '') { $form['disp_topics'] = intval($form['disp_topics']); if ($form['disp_topics'] < 3) { $form['disp_topics'] = 3; } elseif ($form['disp_topics'] > 75) { $form['disp_topics'] = 75; } } if ($form['disp_posts'] != '') { $form['disp_posts'] = intval($form['disp_posts']); if ($form['disp_posts'] < 3) { $form['disp_posts'] = 3; } elseif ($form['disp_posts'] > 75) { $form['disp_posts'] = 75; } } // Make sure we got a valid style string if (Input::post('form_style')) { $styles = \FeatherBB\Core\Lister::getStyles(); $form['style'] = Utils::trim(Input::post('form_style')); if (!in_array($form['style'], $styles)) { throw new Error(__('Bad request'), 404); } } break; case 'privacy': $form = array('email_setting' => intval(Input::post('form_email_setting')), 'notify_with_post' => Input::post('form_notify_with_post') ? '1' : '0', 'auto_notify' => Input::post('form_auto_notify') ? '1' : '0'); if ($form['email_setting'] < 0 || $form['email_setting'] > 2) { $form['email_setting'] = ForumSettings::get('o_default_email_setting'); } break; default: throw new Error(__('Bad request'), 404); } $form = Container::get('hooks')->fire('model.profile.update_profile_form', $form, $section, $id, $info); // Single quotes around non-empty values and nothing for empty values $temp = array(); foreach ($form as $key => $input) { $temp[$key] = $input; } if (empty($temp)) { throw new Error(__('Bad request'), 404); } $update_user = DB::for_table('users')->where('id', $id)->find_one()->set($temp); $update_user = Container::get('hooks')->fireDB('model.profile.update_profile_query', $update_user); $update_user = $update_user->save(); // If we changed the username we have to update some stuff if ($username_updated) { $bans_updated = DB::for_table('bans')->where('username', $info['old_username']); $bans_updated = Container::get('hooks')->fireDB('model.profile.update_profile_bans_updated', $bans_updated); $bans_updated = $bans_updated->update_many('username', $form['username']); $update_poster_id = DB::for_table('posts')->where('poster_id', $id); $update_poster_id = Container::get('hooks')->fireDB('model.profile.update_profile_poster_id', $update_poster_id); $update_poster_id = $update_poster_id->update_many('poster', $form['username']); $update_posts = DB::for_table('posts')->where('edited_by', $info['old_username']); $update_posts = Container::get('hooks')->fireDB('model.profile.update_profile_posts', $update_posts); $update_posts = $update_posts->update_many('edited_by', $form['username']); $update_topics_poster = DB::for_table('topics')->where('poster', $info['old_username']); $update_topics_poster = Container::get('hooks')->fireDB('model.profile.update_profile_topics_poster', $update_topics_poster); $update_topics_poster = $update_topics_poster->update_many('poster', $form['username']); $update_topics_last_poster = DB::for_table('topics')->where('last_poster', $info['old_username']); $update_topics_last_poster = Container::get('hooks')->fireDB('model.profile.update_profile_topics_last_poster', $update_topics_last_poster); $update_topics_last_poster = $update_topics_last_poster->update_many('last_poster', $form['username']); $update_forums = DB::for_table('forums')->where('last_poster', $info['old_username']); $update_forums = Container::get('hooks')->fireDB('model.profile.update_profile_forums', $update_forums); $update_forums = $update_forums->update_many('last_poster', $form['username']); $update_online = DB::for_table('online')->where('ident', $info['old_username']); $update_online = Container::get('hooks')->fireDB('model.profile.update_profile_online', $update_online); $update_online = $update_online->update_many('ident', $form['username']); // If the user is a moderator or an administrator we have to update the moderator lists $group_id = DB::for_table('users')->where('id', $id); // TODO: restore hook // $group_id = Container::get('hooks')->fireDB('model.profile.update_profile_group_id', $update_online); $group_id = $group_id->find_one_col('group_id'); $group_mod = DB::for_table('groups')->where('g_id', $group_id); $group_mod = Container::get('hooks')->fireDB('model.profile.update_profile_group_mod', $group_mod); $group_mod = $group_mod->find_one_col('g_moderator'); if ($group_id == ForumEnv::get('FEATHER_ADMIN') || $group_mod == '1') { // Loop through all forums $result = $this->loop_mod_forums(); foreach ($result as $cur_forum) { $cur_moderators = $cur_forum['moderators'] != '' ? unserialize($cur_forum['moderators']) : array(); if (in_array($id, $cur_moderators)) { unset($cur_moderators[$info['old_username']]); $cur_moderators[$form['username']] = $id; uksort($cur_moderators, 'utf8_strcasecmp'); $update_mods = DB::for_table('forums')->where('id', $cur_forum['id'])->find_one()->set('moderators', serialize($cur_moderators)); $update_mods = Container::get('hooks')->fireDB('model.profile.update_profile_mods', $update_mods); $update_mods = $update_mods->save(); } } } // Regenerate the users info cache if (!Container::get('cache')->isCached('users_info')) { Container::get('cache')->store('users_info', Cache::get_users_info()); } $stats = Container::get('cache')->retrieve('users_info'); // Check if the bans table was updated and regenerate the bans cache when needed if ($bans_updated) { Container::get('cache')->store('bans', Cache::get_bans()); } } $section = Container::get('hooks')->fireDB('model.profile.update_profile', $section, $id); return Router::redirect(Router::pathFor('profileSection', array('id' => $id, 'section' => $section)), __('Profile redirect')); }
public function remove_ban($ban_id) { $ban_id = Container::get('hooks')->fire('model.admin.bans.remove_ban', $ban_id); $result = DB::for_table('bans')->where('id', $ban_id)->find_one(); $result = Container::get('hooks')->fireDB('model.admin.bans.remove_ban_query', $result); $result = $result->delete(); // Regenerate the bans cache Container::get('cache')->store('bans', Cache::get_bans()); return Router::redirect(Router::pathFor('adminBans'), __('Ban removed redirect')); }
public function call() { global $feather_bans; if ($cookie = $this->get_cookie_data($this->app->forum_settings['cookie_name'], $this->app->forum_settings['cookie_seed'])) { $this->app->user = $this->model->load_user($cookie['user_id']); $expires = $cookie['expires'] > $this->app->now + $this->app->forum_settings['o_timeout_visit'] ? $this->app->now + 1209600 : $this->app->now + $this->app->forum_settings['o_timeout_visit']; $this->app->user->is_guest = false; $this->app->user->is_admmod = $this->app->user->g_id == $this->app->forum_env['FEATHER_ADMIN'] || $this->app->user->g_moderator == '1'; if (!$this->app->user->disp_topics) { $this->app->user->disp_topics = $this->app->forum_settings['o_disp_topics_default']; } if (!$this->app->user->disp_posts) { $this->app->user->disp_posts = $this->app->forum_settings['o_disp_posts_default']; } if (!file_exists($this->app->forum_env['FEATHER_ROOT'] . 'featherbb/lang/' . $this->app->user->language)) { $this->app->user->language = $this->app->forum_settings['o_default_lang']; } if (!file_exists($this->app->forum_env['FEATHER_ROOT'] . 'style/themes/' . $this->app->user->style . '/style.css')) { $this->app->user->style = $this->app->forum_settings['o_default_style']; } $this->model->feather_setcookie($this->app->user->id, $this->app->user->password, $expires); $this->update_online(); } else { $this->app->user = $this->model->load_user(1); $this->app->user->disp_topics = $this->app->forum_settings['o_disp_topics_default']; $this->app->user->disp_posts = $this->app->forum_settings['o_disp_posts_default']; $this->app->user->timezone = $this->app->forum_settings['o_default_timezone']; $this->app->user->dst = $this->app->forum_settings['o_default_dst']; $this->app->user->language = $this->app->forum_settings['o_default_lang']; $this->app->user->style = $this->app->forum_settings['o_default_style']; $this->app->user->is_guest = true; $this->app->user->is_admmod = false; // Update online list if (!$this->app->user->logged) { $this->app->user->logged = time(); // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table switch ($this->app->forum_settings['db_type']) { case 'mysql': case 'mysqli': case 'mysql_innodb': case 'mysqli_innodb': case 'sqlite': case 'sqlite3': DB::for_table('online')->raw_execute('REPLACE INTO ' . $this->app->forum_settings['db_prefix'] . 'online (user_id, ident, logged) VALUES(1, :ident, :logged)', array(':ident' => $this->app->request->getIp(), ':logged' => $this->app->user->logged)); break; default: DB::for_table('online')->raw_execute('INSERT INTO ' . $this->app->forum_settings['db_prefix'] . 'online (user_id, ident, logged) SELECT 1, :ident, :logged WHERE NOT EXISTS (SELECT 1 FROM ' . $this->app->db->prefix . 'online WHERE ident=:ident)', array(':ident' => $this->app->request->getIp(), ':logged' => $this->app->user->logged)); break; } } else { DB::for_table('online')->where('ident', $this->app->request->getIp())->update_many('logged', time()); } $this->model->feather_setcookie(1, Random::hash(uniqid(rand(), true)), $this->app->now + 31536000); } load_textdomain('featherbb', $this->app->forum_env['FEATHER_ROOT'] . 'featherbb/lang/' . $this->app->user->language . '/common.mo'); // Load bans from cache if (!$this->app->cache->isCached('bans')) { $this->app->cache->store('bans', Cache::get_bans()); } $feather_bans = $this->app->cache->retrieve('bans'); // Check if current user is banned $this->check_bans(); // Update online list $this->update_users_online(); $this->next->call(); }
public function remove_ban($ban_id) { $ban_id = $this->hook->fire('remove_ban', $ban_id); $result = DB::for_table('bans')->where('id', $ban_id)->find_one(); $result = $this->hook->fireDB('remove_ban_query', $result); $result = $result->delete(); // Regenerate the bans cache $this->feather->cache->store('bans', Cache::get_bans()); Url::redirect($this->feather->urlFor('adminBans'), __('Ban removed redirect')); }
public function __invoke($req, $res, $next) { $authCookie = Container::get('cookie')->get(ForumSettings::get('cookie_name')); if ($jwt = $this->get_cookie_data($authCookie)) { $user = AuthModel::load_user($jwt->data->userId); $expires = $jwt->exp > Container::get('now') + ForumSettings::get('o_timeout_visit') ? Container::get('now') + 1209600 : Container::get('now') + ForumSettings::get('o_timeout_visit'); $user->is_guest = false; $user->is_admmod = $user->g_id == ForumEnv::get('FEATHER_ADMIN') || $user->g_moderator == '1'; if (!$user->disp_topics) { $user->disp_topics = ForumSettings::get('o_disp_topics_default'); } if (!$user->disp_posts) { $user->disp_posts = ForumSettings::get('o_disp_posts_default'); } if (!file_exists(ForumEnv::get('FEATHER_ROOT') . 'featherbb/lang/' . $user->language)) { $user->language = ForumSettings::get('o_default_lang'); } if (!file_exists(ForumEnv::get('FEATHER_ROOT') . 'style/themes/' . $user->style . '/style.css')) { $user->style = ForumSettings::get('o_default_style'); } // Refresh cookie to avoid re-logging between idle $jwt = AuthModel::generate_jwt($user, $expires); AuthModel::feather_setcookie('Bearer ' . $jwt, $expires); // Add user to DIC Container::set('user', $user); $this->update_online(); } else { $user = AuthModel::load_user(1); $user->disp_topics = ForumSettings::get('o_disp_topics_default'); $user->disp_posts = ForumSettings::get('o_disp_posts_default'); $user->timezone = ForumSettings::get('o_default_timezone'); $user->dst = ForumSettings::get('o_default_dst'); $user->language = ForumSettings::get('o_default_lang'); $user->style = ForumSettings::get('o_default_style'); $user->is_guest = true; $user->is_admmod = false; // Update online list if (!$user->logged) { $user->logged = time(); // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table switch (ForumSettings::get('db_type')) { case 'mysql': case 'mysqli': case 'mysql_innodb': case 'mysqli_innodb': case 'sqlite': case 'sqlite3': DB::for_table('online')->raw_execute('REPLACE INTO ' . ForumSettings::get('db_prefix') . 'online (user_id, ident, logged) VALUES(1, :ident, :logged)', array(':ident' => Utils::getIp(), ':logged' => $user->logged)); break; default: DB::for_table('online')->raw_execute('INSERT INTO ' . ForumSettings::get('db_prefix') . 'online (user_id, ident, logged) SELECT 1, :ident, :logged WHERE NOT EXISTS (SELECT 1 FROM ' . ForumSettings::get('db_prefix') . 'online WHERE ident=:ident)', array(':ident' => Utils::getIp(), ':logged' => $user->logged)); break; } } else { DB::for_table('online')->where('ident', Utils::getIp())->update_many('logged', time()); } // $jwt = AuthModel::generate_jwt($user, Container::get('now') + 31536000); // AuthModel::feather_setcookie('Bearer '.$jwt, Container::get('now') + 31536000); // Add $user as guest to DIC Container::set('user', $user); } translate('common'); // Load bans from cache if (!Container::get('cache')->isCached('bans')) { Container::get('cache')->store('bans', Cache::get_bans()); } // Add bans to the container Container::set('bans', Container::get('cache')->retrieve('bans')); // Check if current user is banned $this->check_bans(); // Update online list $this->update_users_online(); return $next($req, $res); }
public function ban_users() { if ($this->request->post('users')) { $user_ids = is_array($this->request->post('users')) ? array_keys($this->request->post('users')) : explode(',', $this->request->post('users')); $user_ids = array_map('intval', $user_ids); // Delete invalid IDs $user_ids = array_diff($user_ids, array(0, 1)); } else { $user_ids = array(); } $user_ids = $this->hook->fire('model.users.ban_users.user_ids', $user_ids); if (empty($user_ids)) { throw new Error(__('No users selected'), 404); } // Are we trying to ban any admins? $is_admin = DB::for_table('users')->where_in('id', $user_ids)->where('group_id', $this->feather->forum_env['FEATHER_ADMIN'])->find_one(); if ($is_admin) { throw new Error(__('No ban admins message'), 403); } // Also, we cannot ban moderators $is_mod = DB::for_table('users')->table_alias('u')->inner_join('groups', array('u.group_id', '=', 'g.g_id'), 'g')->where('g.g_moderator', 1)->where_in('u.id', $user_ids)->find_one(); if ($is_mod) { throw new Error(__('No ban mods message'), 403); } if ($this->request->post('ban_users_comply')) { $ban_message = Utils::trim($this->request->post('ban_message')); $ban_expire = Utils::trim($this->request->post('ban_expire')); $ban_the_ip = $this->request->post('ban_the_ip') ? intval($this->request->post('ban_the_ip')) : 0; $this->hook->fire('model.users.ban_users.comply', $ban_message, $ban_expire, $ban_the_ip); if ($ban_expire != '' && $ban_expire != 'Never') { $ban_expire = strtotime($ban_expire . ' GMT'); if ($ban_expire == -1 || !$ban_expire) { throw new Error(__('Invalid date message') . ' ' . __('Invalid date reasons'), 400); } $diff = ($this->user->timezone + $this->user->dst) * 3600; $ban_expire -= $diff; if ($ban_expire <= time()) { throw new Error(__('Invalid date message') . ' ' . __('Invalid date reasons'), 400); } } else { $ban_expire = 'NULL'; } $ban_message = $ban_message != '' ? $ban_message : 'NULL'; // Fetch user information $user_info = array(); $select_fetch_user_information = array('id', 'username', 'email', 'registration_ip'); $result = DB::for_table('users')->select_many($select_fetch_user_information)->where_in('id', $user_ids); $result = $this->hook->fireDB('model.users.ban_users.user_info_query', $result); $result = $result->find_many(); foreach ($result as $cur_user) { $user_info[$cur_user['id']] = array('username' => $cur_user['username'], 'email' => $cur_user['email'], 'ip' => $cur_user['registration_ip']); } // Overwrite the registration IP with one from the last post (if it exists) if ($ban_the_ip != 0) { $result = DB::for_table('posts')->raw_query('SELECT p.poster_id, p.poster_ip FROM ' . $this->feather->forum_settings['db_prefix'] . 'posts AS p INNER JOIN (SELECT MAX(id) AS id FROM ' . $this->feather->forum_settings['db_prefix'] . 'posts WHERE poster_id IN (' . implode(',', $user_ids) . ') GROUP BY poster_id) AS i ON p.id=i.id')->find_many(); foreach ($result as $cur_address) { $user_info[$cur_address['poster_id']]['ip'] = $cur_address['poster_ip']; } } $user_info = $this->hook->fire('model.users.ban_users.user_info', $user_info); // And insert the bans! foreach ($user_ids as $user_id) { $ban_username = $user_info[$user_id]['username']; $ban_email = $user_info[$user_id]['email']; $ban_ip = $ban_the_ip != 0 ? $user_info[$user_id]['ip'] : 'NULL'; $insert_update_ban = array('username' => $ban_username, 'ip' => $ban_ip, 'email' => $ban_email, 'message' => $ban_message, 'expire' => $ban_expire, 'ban_creator' => $this->user->id); $insert_update_ban = $this->hook->fire('model.users.ban_users.ban_data', $insert_update_ban); if ($this->request->post('mode') == 'add') { $insert_update_ban['ban_creator'] = $this->user->id; DB::for_table('bans')->create()->set($insert_update_ban)->save(); } // Regenerate the bans cache $this->feather->cache->store('bans', Cache::get_bans()); Url::redirect($this->feather->urlFor('adminUsers'), __('Users banned redirect')); } } return $user_ids; }