+
+
+query('SELECT b.id, b.username, b.ip, b.email, b.message, b.expire, b.ban_creator, u.username AS ban_creator_username FROM '.$db->prefix.'bans AS b LEFT JOIN '.$db->prefix.'users AS u ON b.ban_creator=u.id WHERE b.id>0'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '').' ORDER BY '.$db->escape($order_by).' '.$db->escape($direction).' LIMIT '.$start_from.', 50') or error('Unable to fetch ban list', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ {
+ while ($ban_data = $db->fetch_assoc($result))
+ {
+
+ $actions = ''.$lang_admin_common['Edit'].' | '.$lang_admin_common['Remove'].'';
+ $expire = format_time($ban_data['expire'], true);
+
+?>
+
+
+
+query('INSERT INTO '.$db->prefix.'categories (cat_name) VALUES(\''.$db->escape($new_cat_name).'\')') or error('Unable to create category', __FILE__, __LINE__, $db->error());
+
+ redirect('admin_categories.php', $lang_admin_categories['Category added redirect']);
+}
+
+// Delete a category
+else if (isset($_POST['del_cat']) || isset($_POST['del_cat_comply']))
+{
+ confirm_referrer('admin_categories.php');
+
+ $cat_to_delete = intval($_POST['cat_to_delete']);
+ if ($cat_to_delete < 1)
+ message($lang_common['Bad request']);
+
+ if (isset($_POST['del_cat_comply'])) // Delete a category with all forums and posts
+ {
+ @set_time_limit(0);
+
+ $result = $db->query('SELECT id FROM '.$db->prefix.'forums WHERE cat_id='.$cat_to_delete) or error('Unable to fetch forum list', __FILE__, __LINE__, $db->error());
+ $num_forums = $db->num_rows($result);
+
+ for ($i = 0; $i < $num_forums; ++$i)
+ {
+ $cur_forum = $db->result($result, $i);
+
+ // Prune all posts and topics
+ prune($cur_forum, 1, -1);
+
+ // Delete the forum
+ $db->query('DELETE FROM '.$db->prefix.'forums WHERE id='.$cur_forum) or error('Unable to delete forum', __FILE__, __LINE__, $db->error());
+ }
+
+ // Locate any "orphaned redirect topics" and delete them
+ $result = $db->query('SELECT t1.id FROM '.$db->prefix.'topics AS t1 LEFT JOIN '.$db->prefix.'topics AS t2 ON t1.moved_to=t2.id WHERE t2.id IS NULL AND t1.moved_to IS NOT NULL') or error('Unable to fetch redirect topics', __FILE__, __LINE__, $db->error());
+ $num_orphans = $db->num_rows($result);
+
+ if ($num_orphans)
+ {
+ for ($i = 0; $i < $num_orphans; ++$i)
+ $orphans[] = $db->result($result, $i);
+
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $orphans).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
+ }
+
+ // Delete the category
+ $db->query('DELETE FROM '.$db->prefix.'categories WHERE id='.$cat_to_delete) or error('Unable to delete category', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_categories.php', $lang_admin_categories['Category deleted redirect']);
+ }
+ else // If the user hasn't comfirmed the delete
+ {
+ $result = $db->query('SELECT cat_name FROM '.$db->prefix.'categories WHERE id='.$cat_to_delete) or error('Unable to fetch category info', __FILE__, __LINE__, $db->error());
+ $cat_name = $db->result($result);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Categories']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+ generate_admin_menu('categories');
+
+?>
+
+
+
+
+
+
+
+
+query('SELECT id, disp_position FROM '.$db->prefix.'categories ORDER BY disp_position') or error('Unable to fetch category list', __FILE__, __LINE__, $db->error());
+ $num_cats = $db->num_rows($result);
+
+ for ($i = 0; $i < $num_cats; ++$i)
+ {
+ if ($cat_name[$i] == '')
+ message($lang_admin_categories['Must enter name message']);
+
+ if ($cat_order[$i] == '' || preg_match('/[^0-9]/', $cat_order[$i]))
+ message($lang_admin_categories['Must enter integer message']);
+
+ list($cat_id, $position) = $db->fetch_row($result);
+
+ $db->query('UPDATE '.$db->prefix.'categories SET cat_name=\''.$db->escape($cat_name[$i]).'\', disp_position='.$cat_order[$i].' WHERE id='.$cat_id) or error('Unable to update category', __FILE__, __LINE__, $db->error());
+ }
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_categories.php', $lang_admin_categories['Categories updated redirect']);
+}
+
+// Generate an array with all categories
+$result = $db->query('SELECT id, cat_name, disp_position FROM '.$db->prefix.'categories ORDER BY disp_position') or error('Unable to fetch category list', __FILE__, __LINE__, $db->error());
+$num_cats = $db->num_rows($result);
+
+for ($i = 0; $i < $num_cats; ++$i)
+ $cat_list[] = $db->fetch_row($result);
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Categories']);
+define('PUN_ACTIVE_PAGE', 'admin');
+require PUN_ROOT.'header.php';
+
+generate_admin_menu('categories');
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+query('INSERT INTO '.$db->prefix.'censoring (search_for, replace_with) VALUES (\''.$db->escape($search_for).'\', \''.$db->escape($replace_with).'\')') or error('Unable to add censor word', __FILE__, __LINE__, $db->error());
+
+ redirect('admin_censoring.php', $lang_admin_censoring['Word added redirect']);
+}
+
+// Update a censor word
+else if (isset($_POST['update']))
+{
+ confirm_referrer('admin_censoring.php');
+
+ $id = intval(key($_POST['update']));
+
+ $search_for = pun_trim($_POST['search_for'][$id]);
+ $replace_with = pun_trim($_POST['replace_with'][$id]);
+
+ if ($search_for == '' || $replace_with == '')
+ message($lang_admin_censoring['Must search both message']);
+
+ $db->query('UPDATE '.$db->prefix.'censoring SET search_for=\''.$db->escape($search_for).'\', replace_with=\''.$db->escape($replace_with).'\' WHERE id='.$id) or error('Unable to update censor word', __FILE__, __LINE__, $db->error());
+
+ redirect('admin_censoring.php', $lang_admin_censoring['Word updated redirect']);
+}
+
+// Remove a censor word
+else if (isset($_POST['remove']))
+{
+ confirm_referrer('admin_censoring.php');
+
+ $id = intval(key($_POST['remove']));
+
+ $db->query('DELETE FROM '.$db->prefix.'censoring WHERE id='.$id) or error('Unable to delete censor word', __FILE__, __LINE__, $db->error());
+
+ redirect('admin_censoring.php', $lang_admin_censoring['Word removed redirect']);
+}
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Censoring']);
+$focus_element = array('censoring', 'new_search_for');
+define('PUN_ACTIVE_PAGE', 'admin');
+require PUN_ROOT.'header.php';
+
+generate_admin_menu('censoring');
+
+?>
+
+
+
+
+
+
+
+
+query('INSERT INTO '.$db->prefix.'forums (cat_id) VALUES('.$add_to_cat.')') or error('Unable to create forum', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_forums.php', $lang_admin_forums['Forum added redirect']);
+}
+
+// Delete a forum
+else if (isset($_GET['del_forum']))
+{
+ confirm_referrer('admin_forums.php');
+
+ $forum_id = intval($_GET['del_forum']);
+ if ($forum_id < 1)
+ message($lang_common['Bad request']);
+
+ if (isset($_POST['del_forum_comply'])) // Delete a forum with all posts
+ {
+ @set_time_limit(0);
+
+ // Prune all posts and topics
+ prune($forum_id, 1, -1);
+
+ // Locate any "orphaned redirect topics" and delete them
+ $result = $db->query('SELECT t1.id FROM '.$db->prefix.'topics AS t1 LEFT JOIN '.$db->prefix.'topics AS t2 ON t1.moved_to=t2.id WHERE t2.id IS NULL AND t1.moved_to IS NOT NULL') or error('Unable to fetch redirect topics', __FILE__, __LINE__, $db->error());
+ $num_orphans = $db->num_rows($result);
+
+ if ($num_orphans)
+ {
+ for ($i = 0; $i < $num_orphans; ++$i)
+ $orphans[] = $db->result($result, $i);
+
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $orphans).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
+ }
+
+ // Delete the forum and any forum specific group permissions
+ $db->query('DELETE FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to delete forum', __FILE__, __LINE__, $db->error());
+ $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_forums.php', $lang_admin_forums['Forum deleted redirect']);
+ }
+ else // If the user hasn't confirmed the delete
+ {
+ $result = $db->query('SELECT forum_name FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+ $forum_name = pun_htmlspecialchars($db->result($result));
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Forums']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+ generate_admin_menu('forums');
+
+?>
+
+
+
+
+
+
+
+
+ $disp_position)
+ {
+ $disp_position = trim($disp_position);
+ if ($disp_position == '' || preg_match('/[^0-9]/', $disp_position))
+ message($lang_admin_forums['Must be integer message']);
+
+ $db->query('UPDATE '.$db->prefix.'forums SET disp_position='.$disp_position.' WHERE id='.intval($forum_id)) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
+ }
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_forums.php', $lang_admin_forums['Forums updated redirect']);
+}
+
+else if (isset($_GET['edit_forum']))
+{
+ $forum_id = intval($_GET['edit_forum']);
+ if ($forum_id < 1)
+ message($lang_common['Bad request']);
+
+ // Update group permissions for $forum_id
+ if (isset($_POST['save']))
+ {
+ confirm_referrer('admin_forums.php');
+
+ // Start with the forum details
+ $forum_name = pun_trim($_POST['forum_name']);
+ $forum_desc = pun_linebreaks(pun_trim($_POST['forum_desc']));
+ $cat_id = intval($_POST['cat_id']);
+ $sort_by = intval($_POST['sort_by']);
+ $redirect_url = isset($_POST['redirect_url']) ? trim($_POST['redirect_url']) : null;
+
+ if ($forum_name == '')
+ message($lang_admin_forums['Must enter name message']);
+
+ if ($cat_id < 1)
+ message($lang_common['Bad request']);
+
+ $forum_desc = ($forum_desc != '') ? '\''.$db->escape($forum_desc).'\'' : 'NULL';
+ $redirect_url = ($redirect_url != '') ? '\''.$db->escape($redirect_url).'\'' : 'NULL';
+
+ $db->query('UPDATE '.$db->prefix.'forums SET forum_name=\''.$db->escape($forum_name).'\', forum_desc='.$forum_desc.', redirect_url='.$redirect_url.', sort_by='.$sort_by.', cat_id='.$cat_id.' WHERE id='.$forum_id) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
+
+ // Now let's deal with the permissions
+ if (isset($_POST['read_forum_old']))
+ {
+ $result = $db->query('SELECT g_id, g_read_board, g_post_replies, g_post_topics FROM '.$db->prefix.'groups WHERE g_id!='.PUN_ADMIN) or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
+ while ($cur_group = $db->fetch_assoc($result))
+ {
+ $read_forum_new = ($cur_group['g_read_board'] == '1') ? isset($_POST['read_forum_new'][$cur_group['g_id']]) ? '1' : '0' : intval($_POST['read_forum_old'][$cur_group['g_id']]);
+ $post_replies_new = isset($_POST['post_replies_new'][$cur_group['g_id']]) ? '1' : '0';
+ $post_topics_new = isset($_POST['post_topics_new'][$cur_group['g_id']]) ? '1' : '0';
+
+ // Check if the new settings differ from the old
+ if ($read_forum_new != $_POST['read_forum_old'][$cur_group['g_id']] || $post_replies_new != $_POST['post_replies_old'][$cur_group['g_id']] || $post_topics_new != $_POST['post_topics_old'][$cur_group['g_id']])
+ {
+ // If the new settings are identical to the default settings for this group, delete it's row in forum_perms
+ if ($read_forum_new == '1' && $post_replies_new == $cur_group['g_post_replies'] && $post_topics_new == $cur_group['g_post_topics'])
+ $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE group_id='.$cur_group['g_id'].' AND forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
+ else
+ {
+ // Run an UPDATE and see if it affected a row, if not, INSERT
+ $db->query('UPDATE '.$db->prefix.'forum_perms SET read_forum='.$read_forum_new.', post_replies='.$post_replies_new.', post_topics='.$post_topics_new.' WHERE group_id='.$cur_group['g_id'].' AND forum_id='.$forum_id) or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
+ if (!$db->affected_rows())
+ $db->query('INSERT INTO '.$db->prefix.'forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) VALUES('.$cur_group['g_id'].', '.$forum_id.', '.$read_forum_new.', '.$post_replies_new.', '.$post_topics_new.')') or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
+ }
+ }
+ }
+ }
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_forums.php', $lang_admin_forums['Forum updated redirect']);
+ }
+ else if (isset($_POST['revert_perms']))
+ {
+ confirm_referrer('admin_forums.php');
+
+ $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_forums.php?edit_forum='.$forum_id, $lang_admin_forums['Perms reverted redirect']);
+ }
+
+ // Fetch forum info
+ $result = $db->query('SELECT id, forum_name, forum_desc, redirect_url, num_topics, sort_by, cat_id FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $cur_forum = $db->fetch_assoc($result);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Forums']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+ generate_admin_menu('forums');
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.disp_position FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
+
+if ($db->num_rows($result) > 0)
+{
+
+?>
+
+
+
'."\n\t\t\t\t\t".''."\n\t\t\t\t".'
'."\n";
+
+?>
+
+
+
+
+
+
+
+
+
+
+query('SELECT * FROM '.$db->prefix.'groups WHERE g_id='.$base_group) or error('Unable to fetch user group info', __FILE__, __LINE__, $db->error());
+ $group = $db->fetch_assoc($result);
+
+ $mode = 'add';
+ }
+ else // We are editing a group
+ {
+ $group_id = intval($_GET['edit_group']);
+ if ($group_id < 1)
+ message($lang_common['Bad request']);
+
+ $result = $db->query('SELECT * FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to fetch user group info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $group = $db->fetch_assoc($result);
+
+ $mode = 'edit';
+ }
+
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['User groups']);
+ $required_fields = array('req_title' => $lang_admin_groups['Group title label']);
+ $focus_element = array('groups2', 'req_title');
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+ generate_admin_menu('groups');
+
+?>
+
+
+
+
+
+
+
+
+escape($user_title).'\'' : 'NULL';
+
+ if ($_POST['mode'] == 'add')
+ {
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\'') or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ message(sprintf($lang_admin_groups['Title already exists message'], pun_htmlspecialchars($title)));
+
+ $db->query('INSERT INTO '.$db->prefix.'groups (g_title, g_user_title, g_moderator, g_mod_edit_users, g_mod_rename_users, g_mod_change_passwords, g_mod_ban_users, g_read_board, g_view_users, g_post_replies, g_post_topics, g_edit_posts, g_delete_posts, g_delete_topics, g_set_title, g_search, g_search_users, g_send_email, g_post_flood, g_search_flood, g_email_flood) VALUES(\''.$db->escape($title).'\', '.$user_title.', '.$moderator.', '.$mod_edit_users.', '.$mod_rename_users.', '.$mod_change_passwords.', '.$mod_ban_users.', '.$read_board.', '.$view_users.', '.$post_replies.', '.$post_topics.', '.$edit_posts.', '.$delete_posts.', '.$delete_topics.', '.$set_title.', '.$search.', '.$search_users.', '.$send_email.', '.$post_flood.', '.$search_flood.', '.$email_flood.')') or error('Unable to add group', __FILE__, __LINE__, $db->error());
+ $new_group_id = $db->insert_id();
+
+ // Now lets copy the forum specific permissions from the group which this group is based on
+ $result = $db->query('SELECT forum_id, read_forum, post_replies, post_topics FROM '.$db->prefix.'forum_perms WHERE group_id='.intval($_POST['base_group'])) or error('Unable to fetch group forum permission list', __FILE__, __LINE__, $db->error());
+ while ($cur_forum_perm = $db->fetch_assoc($result))
+ $db->query('INSERT INTO '.$db->prefix.'forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) VALUES('.$new_group_id.', '.$cur_forum_perm['forum_id'].', '.$cur_forum_perm['read_forum'].', '.$cur_forum_perm['post_replies'].', '.$cur_forum_perm['post_topics'].')') or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
+ }
+ else
+ {
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\' AND g_id!='.intval($_POST['group_id'])) or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ message(sprintf($lang_admin_groups['Title already exists message'], pun_htmlspecialchars($title)));
+
+ $db->query('UPDATE '.$db->prefix.'groups SET g_title=\''.$db->escape($title).'\', g_user_title='.$user_title.', g_moderator='.$moderator.', g_mod_edit_users='.$mod_edit_users.', g_mod_rename_users='.$mod_rename_users.', g_mod_change_passwords='.$mod_change_passwords.', g_mod_ban_users='.$mod_ban_users.', g_read_board='.$read_board.', g_view_users='.$view_users.', g_post_replies='.$post_replies.', g_post_topics='.$post_topics.', g_edit_posts='.$edit_posts.', g_delete_posts='.$delete_posts.', g_delete_topics='.$delete_topics.', g_set_title='.$set_title.', g_search='.$search.', g_search_users='.$search_users.', g_send_email='.$send_email.', g_post_flood='.$post_flood.', g_search_flood='.$search_flood.', g_email_flood='.$email_flood.' WHERE g_id='.intval($_POST['group_id'])) or error('Unable to update group', __FILE__, __LINE__, $db->error());
+ }
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ if ($_POST['mode'] == 'edit')
+ redirect('admin_groups.php', $lang_admin_groups['Group edited redirect']);
+ else
+ redirect('admin_groups.php', $lang_admin_groups['Group added redirect']);
+}
+
+
+// Set default group
+else if (isset($_POST['set_default_group']))
+{
+ confirm_referrer('admin_groups.php');
+
+ $group_id = intval($_POST['default_group']);
+
+ // Make sure it's not the admin or guest groups
+ if ($group_id == PUN_ADMIN || $group_id == PUN_GUEST)
+ message($lang_common['Bad request']);
+
+ // Make sure it's not a moderator group
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_id='.$group_id.' AND g_moderator=0') or error('Unable to check group moderator status', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $db->query('UPDATE '.$db->prefix.'config SET conf_value='.$group_id.' WHERE conf_name=\'o_default_user_group\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the config cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_config_cache();
+
+ redirect('admin_groups.php', $lang_admin_groups['Default group redirect']);
+}
+
+
+// Remove a group
+else if (isset($_GET['del_group']))
+{
+ confirm_referrer('admin_groups.php');
+
+ $group_id = isset($_POST['group_to_delete']) ? intval($_POST['group_to_delete']) : intval($_GET['del_group']);
+ if ($group_id < 5)
+ message($lang_common['Bad request']);
+
+ // Make sure we don't remove the default group
+ if ($group_id == $pun_config['o_default_user_group'])
+ message($lang_admin_groups['Cannot remove default message']);
+
+ // Check if this group has any members
+ $result = $db->query('SELECT g.g_title, COUNT(u.id) FROM '.$db->prefix.'groups AS g INNER JOIN '.$db->prefix.'users AS u ON g.g_id=u.group_id WHERE g.g_id='.$group_id.' GROUP BY g.g_id, g_title') or error('Unable to fetch group info', __FILE__, __LINE__, $db->error());
+
+ // If the group doesn't have any members or if we've already selected a group to move the members to
+ if (!$db->num_rows($result) || isset($_POST['del_group']))
+ {
+ if (isset($_POST['del_group_comply']) || isset($_POST['del_group']))
+ {
+ if (isset($_POST['del_group']))
+ {
+ $move_to_group = intval($_POST['move_to_group']);
+ $db->query('UPDATE '.$db->prefix.'users SET group_id='.$move_to_group.' WHERE group_id='.$group_id) or error('Unable to move users into group', __FILE__, __LINE__, $db->error());
+ }
+
+ // Delete the group and any forum specific permissions
+ $db->query('DELETE FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to delete group', __FILE__, __LINE__, $db->error());
+ $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE group_id='.$group_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the quick jump cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_quickjump_cache();
+
+ redirect('admin_groups.php', $lang_admin_groups['Group removed redirect']);
+ }
+ else
+ {
+ $result = $db->query('SELECT g_title FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to fetch group title', __FILE__, __LINE__, $db->error());
+ $group_title = $db->result($result);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['User groups']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+ generate_admin_menu('groups');
+
+?>
+
'."\n";
+
+ if ($cur_item['id'] == $cur_item['first_post_id'])
+ update_search_index('post', $cur_item['id'], $cur_item['message'], $cur_item['subject']);
+ else
+ update_search_index('post', $cur_item['id'], $cur_item['message']);
+
+ $end_at = $cur_item['id'];
+ }
+
+ // Check if there is more work to do
+ if ($end_at > 0)
+ {
+ $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE id > '.$end_at.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch next ID', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result) > 0)
+ $query_str = '?i_per_page='.$per_page.'&i_start_at='.$db->result($result);
+ }
+
+ $db->end_transaction();
+ $db->close();
+
+ exit('
');
+}
+
+
+// Get the first post ID from the db
+$result = $db->query('SELECT id FROM '.$db->prefix.'posts ORDER BY id ASC LIMIT 1') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+if ($db->num_rows($result))
+ $first_id = $db->result($result);
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Maintenance']);
+define('PUN_ACTIVE_PAGE', 'admin');
+require PUN_ROOT.'header.php';
+
+generate_admin_menu('maintenance');
+
+?>
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'ranks WHERE min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ message(sprintf($lang_admin_ranks['Dupe min posts message'], $min_posts));
+
+ $db->query('INSERT INTO '.$db->prefix.'ranks (rank, min_posts) VALUES(\''.$db->escape($rank).'\', '.$min_posts.')') or error('Unable to add rank', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the ranks cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_ranks_cache();
+
+ redirect('admin_ranks.php', $lang_admin_ranks['Rank added redirect']);
+}
+
+
+// Update a rank
+else if (isset($_POST['update']))
+{
+ confirm_referrer('admin_ranks.php');
+
+ $id = intval(key($_POST['update']));
+
+ $rank = pun_trim($_POST['rank'][$id]);
+ $min_posts = trim($_POST['min_posts'][$id]);
+
+ if ($rank == '')
+ message($lang_admin_ranks['Must enter title message']);
+
+ if ($min_posts == '' || preg_match('/[^0-9]/', $min_posts))
+ message($lang_admin_ranks['Must be integer message']);
+
+ // Make sure there isn't already a rank with the same min_posts value
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'ranks WHERE id!='.$id.' AND min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ message(sprintf($lang_admin_ranks['Dupe min posts message'], $min_posts));
+
+ $db->query('UPDATE '.$db->prefix.'ranks SET rank=\''.$db->escape($rank).'\', min_posts='.$min_posts.' WHERE id='.$id) or error('Unable to update rank', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the ranks cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_ranks_cache();
+
+ redirect('admin_ranks.php', $lang_admin_ranks['Rank updated redirect']);
+}
+
+
+// Remove a rank
+else if (isset($_POST['remove']))
+{
+ confirm_referrer('admin_ranks.php');
+
+ $id = intval(key($_POST['remove']));
+
+ $db->query('DELETE FROM '.$db->prefix.'ranks WHERE id='.$id) or error('Unable to delete rank', __FILE__, __LINE__, $db->error());
+
+ // Regenerate the ranks cache
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_ranks_cache();
+
+ redirect('admin_ranks.php', $lang_admin_ranks['Rank removed redirect']);
+}
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Ranks']);
+$focus_element = array('ranks', 'new_rank');
+define('PUN_ACTIVE_PAGE', 'admin');
+require PUN_ROOT.'header.php';
+
+generate_admin_menu('ranks');
+
+?>
+
+
+
+
+
+
+
+
+query('SELECT zapped FROM '.$db->prefix.'reports WHERE id='.$zap_id) or error('Unable to fetch report info', __FILE__, __LINE__, $db->error());
+ $zapped = $db->result($result);
+
+ if ($zapped == '')
+ $db->query('UPDATE '.$db->prefix.'reports SET zapped='.time().', zapped_by='.$pun_user['id'].' WHERE id='.$zap_id) or error('Unable to zap report', __FILE__, __LINE__, $db->error());
+
+ redirect('admin_reports.php', $lang_admin_reports['Report zapped redirect']);
+}
+
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Reports']);
+define('PUN_ACTIVE_PAGE', 'admin');
+require PUN_ROOT.'header.php';
+
+generate_admin_menu('reports');
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+query('SELECT r.id, r.topic_id, r.forum_id, r.reported_by, r.message, r.zapped, r.zapped_by AS zapped_by_id, p.id AS pid, t.subject, f.forum_name, u.username AS reporter, u2.username AS zapped_by FROM '.$db->prefix.'reports AS r LEFT JOIN '.$db->prefix.'posts AS p ON r.post_id=p.id LEFT JOIN '.$db->prefix.'topics AS t ON r.topic_id=t.id LEFT JOIN '.$db->prefix.'forums AS f ON r.forum_id=f.id LEFT JOIN '.$db->prefix.'users AS u ON r.reported_by=u.id LEFT JOIN '.$db->prefix.'users AS u2 ON r.zapped_by=u2.id WHERE r.zapped IS NOT NULL ORDER BY zapped DESC LIMIT 10') or error('Unable to fetch report list', __FILE__, __LINE__, $db->error());
+
+if ($db->num_rows($result))
+{
+ while ($cur_report = $db->fetch_assoc($result))
+ {
+ $reporter = ($cur_report['reporter'] != '') ? ''.pun_htmlspecialchars($cur_report['reporter']).'' : $lang_admin_reports['Deleted user'];
+ $forum = ($cur_report['forum_name'] != '') ? ''.pun_htmlspecialchars($cur_report['forum_name']).'' : ''.$lang_admin_reports['Deleted'].'';
+ $topic = ($cur_report['subject'] != '') ? '» '.pun_htmlspecialchars($cur_report['subject']).'' : '» '.$lang_admin_reports['Deleted'].'';
+ $post = str_replace("\n", ' ', pun_htmlspecialchars($cur_report['message']));
+ $post_id = ($cur_report['pid'] != '') ? '» Post #'.$cur_report['pid'].'' : '» '.$lang_admin_reports['Deleted'].'';
+ $zapped_by = ($cur_report['zapped_by'] != '') ? ''.pun_htmlspecialchars($cur_report['zapped_by']).'' : $lang_admin_reports['NA'];
+ $zapped_by = ($cur_report['zapped_by'] != '') ? ''.pun_htmlspecialchars($cur_report['zapped_by']).'' : $lang_admin_reports['NA'];
+ $report_location = array($forum, $topic, $post_id);
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+query('SELECT poster_ip, MAX(posted) AS last_used FROM '.$db->prefix.'posts WHERE poster_id='.$ip_stats.' GROUP BY poster_ip') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $num_ips = $db->num_rows($result);
+
+ // Determine the ip offset (based on $_GET['p'])
+ $num_pages = ceil($num_ips / 50);
+
+ $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
+ $start_from = 50 * ($p - 1);
+
+ // Generate paging links
+ $paging_links = ''.$lang_common['Pages'].' '.paginate($num_pages, $p, 'admin_users.php?ip_stats='.$ip_stats );
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Users'], $lang_admin_users['Results head']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
»
+
»
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+query('SELECT poster_ip, MAX(posted) AS last_used, COUNT(id) AS used_times FROM '.$db->prefix.'posts WHERE poster_id='.$ip_stats.' GROUP BY poster_ip ORDER BY last_used DESC LIMIT '.$start_from.', 50') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ {
+ while ($cur_ip = $db->fetch_assoc($result))
+ {
+
+?>
+
+
+
+query('SELECT DISTINCT poster_id, poster FROM '.$db->prefix.'posts WHERE poster_ip=\''.$db->escape($ip).'\' ORDER BY poster DESC') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $num_posts = $db->num_rows($result);
+
+ if ($num_posts)
+ {
+ // Loop through users and print out some info
+ for ($i = 0; $i < $num_posts; ++$i)
+ {
+ list($poster_id, $poster) = $db->fetch_row($result);
+
+ $result2 = $db->query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1 AND u.id='.$poster_id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+
+ if (($user_data = $db->fetch_assoc($result2)))
+ {
+ $user_title = get_title($user_data);
+
+ $actions = ''.$lang_admin_users['Results view IP link'].' | '.$lang_admin_users['Results show posts link'].'';
+
+?>
+
+'.$last_post_after;
+ }
+ if ($last_post_before != '')
+ {
+ $query_str[] = 'last_post_before='.$last_post_before;
+
+ $last_post_before = strtotime($last_post_before);
+ if ($last_post_before === false || $last_post_before == -1)
+ message($lang_admin_users['Invalid date time message']);
+
+ $conditions[] = 'u.last_post<'.$last_post_before;
+ }
+ if ($registered_after != '')
+ {
+ $query_str[] = 'registered_after='.$registered_after;
+
+ $registered_after = strtotime($registered_after);
+ if ($registered_after === false || $registered_after == -1)
+ message($lang_admin_users['Invalid date time message']);
+
+ $conditions[] = 'u.registered>'.$registered_after;
+ }
+ if ($registered_before != '')
+ {
+ $query_str[] = 'registered_before='.$registered_before;
+
+ $registered_before = strtotime($registered_before);
+ if ($registered_before === false || $registered_before == -1)
+ message($lang_admin_users['Invalid date time message']);
+
+ $conditions[] = 'u.registered<'.$registered_before;
+ }
+
+ $like_command = ($db_type == 'pgsql') ? 'ILIKE' : 'LIKE';
+ foreach ($form as $key => $input)
+ {
+ if ($input != '' && in_array($key, array('username', 'email', 'title', 'realname', 'url', 'jabber', 'icq', 'msn', 'aim', 'yahoo', 'location', 'signature', 'admin_note')))
+ {
+ $conditions[] = 'u.'.$db->escape($key).' '.$like_command.' \''.$db->escape(str_replace('*', '%', $input)).'\'';
+ $query_str[] = 'form%5B'.$key.'%5D='.urlencode($input);
+ }
+ }
+
+ if ($posts_greater != '')
+ {
+ $query_str[] = 'posts_greater='.$posts_greater;
+ $conditions[] = 'u.num_posts>'.$posts_greater;
+ }
+ if ($posts_less != '')
+ {
+ $query_str[] = 'posts_less='.$posts_less;
+ $conditions[] = 'u.num_posts<'.$posts_less;
+ }
+
+ if ($user_group > -1)
+ $conditions[] = 'u.group_id='.$user_group;
+
+ // Fetch user count
+ $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+ $num_users = $db->result($result);
+
+ // Determine the user offset (based on $_GET['p'])
+ $num_pages = ceil($num_users / 50);
+
+ $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
+ $start_from = 50 * ($p - 1);
+
+ // Generate paging links
+ $paging_links = ''.$lang_common['Pages'].' '.paginate($num_pages, $p, 'admin_users.php?find_user=&'.implode('&', $query_str));
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Users'], $lang_admin_users['Results head']);
+ define('PUN_ACTIVE_PAGE', 'admin');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
»
+
»
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '').' ORDER BY '.$db->escape($order_by).' '.$db->escape($direction).' LIMIT '.$start_from.', 50') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ {
+ while ($user_data = $db->fetch_assoc($result))
+ {
+ $user_title = get_title($user_data);
+
+ // This script is a special case in that we want to display "Not verified" for non-verified users
+ if (($user_data['g_id'] == '' || $user_data['g_id'] == PUN_UNVERIFIED) && $user_title != $lang_common['Banned'])
+ $user_title = ''.$lang_admin_users['Not verified'].'';
+
+ $actions = ''.$lang_admin_users['Results view IP link'].' | '.$lang_admin_users['Results show posts link'].'';
+
+?>
+
+..
diff --git a/img/index.html b/img/index.html
new file mode 100644
index 0000000..89337b2
--- /dev/null
+++ b/img/index.html
@@ -0,0 +1 @@
+..
diff --git a/img/smilies/big_smile.png b/img/smilies/big_smile.png
new file mode 100644
index 0000000..b29719b
Binary files /dev/null and b/img/smilies/big_smile.png differ
diff --git a/img/smilies/cool.png b/img/smilies/cool.png
new file mode 100644
index 0000000..a875361
Binary files /dev/null and b/img/smilies/cool.png differ
diff --git a/img/smilies/hmm.png b/img/smilies/hmm.png
new file mode 100644
index 0000000..69e416a
Binary files /dev/null and b/img/smilies/hmm.png differ
diff --git a/img/smilies/index.html b/img/smilies/index.html
new file mode 100644
index 0000000..89337b2
--- /dev/null
+++ b/img/smilies/index.html
@@ -0,0 +1 @@
+..
diff --git a/img/smilies/lol.png b/img/smilies/lol.png
new file mode 100644
index 0000000..dd9058b
Binary files /dev/null and b/img/smilies/lol.png differ
diff --git a/img/smilies/mad.png b/img/smilies/mad.png
new file mode 100644
index 0000000..011079d
Binary files /dev/null and b/img/smilies/mad.png differ
diff --git a/img/smilies/neutral.png b/img/smilies/neutral.png
new file mode 100644
index 0000000..9bc5ca0
Binary files /dev/null and b/img/smilies/neutral.png differ
diff --git a/img/smilies/roll.png b/img/smilies/roll.png
new file mode 100644
index 0000000..e2e8e2a
Binary files /dev/null and b/img/smilies/roll.png differ
diff --git a/img/smilies/sad.png b/img/smilies/sad.png
new file mode 100644
index 0000000..c14e144
Binary files /dev/null and b/img/smilies/sad.png differ
diff --git a/img/smilies/smile.png b/img/smilies/smile.png
new file mode 100644
index 0000000..44cc239
Binary files /dev/null and b/img/smilies/smile.png differ
diff --git a/img/smilies/tongue.png b/img/smilies/tongue.png
new file mode 100644
index 0000000..5302c89
Binary files /dev/null and b/img/smilies/tongue.png differ
diff --git a/img/smilies/wink.png b/img/smilies/wink.png
new file mode 100644
index 0000000..595c1fe
Binary files /dev/null and b/img/smilies/wink.png differ
diff --git a/img/smilies/yikes.png b/img/smilies/yikes.png
new file mode 100644
index 0000000..bb4aefd
Binary files /dev/null and b/img/smilies/yikes.png differ
diff --git a/img/test.png b/img/test.png
new file mode 100644
index 0000000..7b46d9e
Binary files /dev/null and b/img/test.png differ
diff --git a/include/cache.php b/include/cache.php
new file mode 100644
index 0000000..55d0e96
--- /dev/null
+++ b/include/cache.php
@@ -0,0 +1,145 @@
+query('SELECT * FROM '.$db->prefix.'config', true) or error('Unable to fetch forum config', __FILE__, __LINE__, $db->error());
+ while ($cur_config_item = $db->fetch_row($result))
+ $output[$cur_config_item[0]] = $cur_config_item[1];
+
+ // Output config as PHP code
+ $fh = @fopen(FORUM_CACHE_DIR.'cache_config.php', 'wb');
+ if (!$fh)
+ error('Unable to write configuration cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
+
+ fwrite($fh, '');
+
+ fclose($fh);
+}
+
+
+//
+// Generate the bans cache PHP script
+//
+function generate_bans_cache()
+{
+ global $db;
+
+ // Get the ban list from the DB
+ $result = $db->query('SELECT * FROM '.$db->prefix.'bans', true) or error('Unable to fetch ban list', __FILE__, __LINE__, $db->error());
+
+ $output = array();
+ while ($cur_ban = $db->fetch_assoc($result))
+ $output[] = $cur_ban;
+
+ // Output ban list as PHP code
+ $fh = @fopen(FORUM_CACHE_DIR.'cache_bans.php', 'wb');
+ if (!$fh)
+ error('Unable to write bans cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
+
+ fwrite($fh, '');
+
+ fclose($fh);
+}
+
+
+//
+// Generate the ranks cache PHP script
+//
+function generate_ranks_cache()
+{
+ global $db;
+
+ // Get the rank list from the DB
+ $result = $db->query('SELECT * FROM '.$db->prefix.'ranks ORDER BY min_posts', true) or error('Unable to fetch rank list', __FILE__, __LINE__, $db->error());
+
+ $output = array();
+ while ($cur_rank = $db->fetch_assoc($result))
+ $output[] = $cur_rank;
+
+ // Output ranks list as PHP code
+ $fh = @fopen(FORUM_CACHE_DIR.'cache_ranks.php', 'wb');
+ if (!$fh)
+ error('Unable to write ranks cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
+
+ fwrite($fh, '');
+
+ fclose($fh);
+}
+
+
+//
+// Generate quick jump cache PHP scripts
+//
+function generate_quickjump_cache($group_id = false)
+{
+ global $db, $lang_common, $pun_user;
+
+ // If a group_id was supplied, we generate the quick jump cache for that group only
+ if ($group_id !== false)
+ $groups[0] = $group_id;
+ else
+ {
+ // A group_id was now supplied, so we generate the quick jump cache for all groups
+ $result = $db->query('SELECT g_id FROM '.$db->prefix.'groups') or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
+ $num_groups = $db->num_rows($result);
+
+ for ($i = 0; $i < $num_groups; ++$i)
+ $groups[] = $db->result($result, $i);
+ }
+
+ // Loop through the groups in $groups and output the cache for each of them
+ foreach ($groups as $group_id)
+ {
+ // Output quick jump as PHP code
+ $fh = @fopen(FORUM_CACHE_DIR.'cache_quickjump_'.$group_id.'.php', 'wb');
+ if (!$fh)
+ error('Unable to write quick jump cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
+
+ $output = '';
+ $output .= "\t\t\t\t".''."\n";
+
+ fwrite($fh, $output);
+
+ fclose($fh);
+ }
+}
+
+define('FORUM_CACHE_FUNCTIONS_LOADED', true);
diff --git a/include/common.php b/include/common.php
new file mode 100644
index 0000000..1ad999b
--- /dev/null
+++ b/include/common.php
@@ -0,0 +1,182 @@
+install.php to install FluxBB first.');
+
+// Load the functions script
+require PUN_ROOT.'include/functions.php';
+
+// Load UTF-8 functions
+require PUN_ROOT.'include/utf8/utf8.php';
+
+// Strip out "bad" UTF-8 characters
+forum_remove_bad_characters();
+
+// Reverse the effect of register_globals
+forum_unregister_globals();
+
+// Record the start time (will be used to calculate the generation time for the page)
+$pun_start = get_microtime();
+
+// Make sure PHP reports all errors except E_NOTICE. FluxBB supports E_ALL, but a lot of scripts it may interact with, do not
+error_reporting(E_ALL ^ E_NOTICE);
+
+// Force POSIX locale (to prevent functions such as strtolower() from messing up UTF-8 strings)
+setlocale(LC_CTYPE, 'C');
+
+// Turn off magic_quotes_runtime
+if (get_magic_quotes_runtime())
+ set_magic_quotes_runtime(0);
+
+// Strip slashes from GET/POST/COOKIE (if magic_quotes_gpc is enabled)
+if (get_magic_quotes_gpc())
+{
+ function stripslashes_array($array)
+ {
+ return is_array($array) ? array_map('stripslashes_array', $array) : stripslashes($array);
+ }
+
+ $_GET = stripslashes_array($_GET);
+ $_POST = stripslashes_array($_POST);
+ $_COOKIE = stripslashes_array($_COOKIE);
+ $_REQUEST = stripslashes_array($_REQUEST);
+}
+
+// If a cookie name is not specified in config.php, we use the default (pun_cookie)
+if (empty($cookie_name))
+ $cookie_name = 'pun_cookie';
+
+// If the cache directory is not specified, we use the default setting
+if (!defined('FORUM_CACHE_DIR'))
+ define('FORUM_CACHE_DIR', PUN_ROOT.'cache/');
+
+// Define a few commonly used constants
+define('PUN_UNVERIFIED', 0);
+define('PUN_ADMIN', 1);
+define('PUN_MOD', 2);
+define('PUN_GUEST', 3);
+define('PUN_MEMBER', 4);
+
+// Load DB abstraction layer and connect
+require PUN_ROOT.'include/dblayer/common_db.php';
+
+// Start a transaction
+$db->start_transaction();
+
+// Load cached config
+if (file_exists(FORUM_CACHE_DIR.'cache_config.php'))
+ include FORUM_CACHE_DIR.'cache_config.php';
+
+if (!defined('PUN_CONFIG_LOADED'))
+{
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_config_cache();
+ require FORUM_CACHE_DIR.'cache_config.php';
+}
+
+// Verify that we are running the proper database schema revision
+if (!isset($pun_config['o_database_revision']) || $pun_config['o_database_revision'] < FORUM_DB_REVISION ||
+ !isset($pun_config['o_searchindex_revision']) || $pun_config['o_searchindex_revision'] < FORUM_SI_REVISION ||
+ !isset($pun_config['o_parser_revision']) || $pun_config['o_parser_revision'] < FORUM_PARSER_REVISION ||
+ version_compare($pun_config['o_cur_version'], FORUM_VERSION, '<'))
+ exit('Your FluxBB database is out-of-date and must be upgraded in order to continue. Please run db_update.php in order to complete the upgrade process.');
+
+// Enable output buffering
+if (!defined('PUN_DISABLE_BUFFERING'))
+{
+ // Should we use gzip output compression?
+ if ($pun_config['o_gzip'] && extension_loaded('zlib'))
+ ob_start('ob_gzhandler');
+ else
+ ob_start();
+}
+
+// Define standard date/time formats
+$forum_time_formats = array($pun_config['o_time_format'], 'H:i:s', 'H:i', 'g:i:s a', 'g:i a');
+$forum_date_formats = array($pun_config['o_date_format'], 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y');
+
+// Check/update/set cookie and fetch user info
+$pun_user = array();
+check_cookie($pun_user);
+
+// Attempt to load the common language file
+if (file_exists(PUN_ROOT.'lang/'.$pun_user['language'].'/common.php'))
+ include PUN_ROOT.'lang/'.$pun_user['language'].'/common.php';
+else
+ error('There is no valid language pack \''.pun_htmlspecialchars($pun_user['language']).'\' installed. Please reinstall a language of that name');
+
+// Check if we are to display a maintenance message
+if ($pun_config['o_maintenance'] && $pun_user['g_id'] > PUN_ADMIN && !defined('PUN_TURN_OFF_MAINT'))
+ maintenance_message();
+
+// Load cached bans
+if (file_exists(FORUM_CACHE_DIR.'cache_bans.php'))
+ include FORUM_CACHE_DIR.'cache_bans.php';
+
+if (!defined('PUN_BANS_LOADED'))
+{
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_bans_cache();
+ require FORUM_CACHE_DIR.'cache_bans.php';
+}
+
+// Check if current user is banned
+check_bans();
+
+// Update online list
+update_users_online();
+
+// Check to see if we logged in without a cookie being set
+if ($pun_user['is_guest'] && isset($_GET['login']))
+ message($lang_common['No cookie']);
+
+if (!defined('PUN_MAX_POSTSIZE'))
+ define('PUN_MAX_POSTSIZE', 65535);
+
+if (!defined('PUN_SEARCH_MIN_WORD'))
+ define('PUN_SEARCH_MIN_WORD', 3);
+if (!defined('PUN_SEARCH_MAX_WORD'))
+ define('PUN_SEARCH_MAX_WORD', 20);
diff --git a/include/common_admin.php b/include/common_admin.php
new file mode 100644
index 0000000..7a5603d
--- /dev/null
+++ b/include/common_admin.php
@@ -0,0 +1,133 @@
+
+
+
+query('SELECT id FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id.$extra_sql, true) or error('Unable to fetch topics', __FILE__, __LINE__, $db->error());
+
+ $topic_ids = '';
+ while ($row = $db->fetch_row($result))
+ $topic_ids .= (($topic_ids != '') ? ',' : '').$row[0];
+
+ if ($topic_ids != '')
+ {
+ // Fetch posts to prune
+ $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id IN('.$topic_ids.')', true) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
+
+ $post_ids = '';
+ while ($row = $db->fetch_row($result))
+ $post_ids .= (($post_ids != '') ? ',' : '').$row[0];
+
+ if ($post_ids != '')
+ {
+ // Delete topics
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.$topic_ids.')') or error('Unable to prune topics', __FILE__, __LINE__, $db->error());
+ // Delete subscriptions
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id IN('.$topic_ids.')') or error('Unable to prune subscriptions', __FILE__, __LINE__, $db->error());
+ // Delete posts
+ $db->query('DELETE FROM '.$db->prefix.'posts WHERE id IN('.$post_ids.')') or error('Unable to prune posts', __FILE__, __LINE__, $db->error());
+
+ // We removed a bunch of posts, so now we have to update the search index
+ require_once PUN_ROOT.'include/search_idx.php';
+ strip_search_index($post_ids);
+ }
+ }
+}
diff --git a/include/dblayer/common_db.php b/include/dblayer/common_db.php
new file mode 100644
index 0000000..121d895
--- /dev/null
+++ b/include/dblayer/common_db.php
@@ -0,0 +1,48 @@
+..
diff --git a/include/dblayer/mysql.php b/include/dblayer/mysql.php
new file mode 100644
index 0000000..c595da4
--- /dev/null
+++ b/include/dblayer/mysql.php
@@ -0,0 +1,347 @@
+ 'INT(10) UNSIGNED AUTO_INCREMENT'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ $this->prefix = $db_prefix;
+
+ if ($p_connect)
+ $this->link_id = @mysql_pconnect($db_host, $db_username, $db_password);
+ else
+ $this->link_id = @mysql_connect($db_host, $db_username, $db_password);
+
+ if ($this->link_id)
+ {
+ if (!@mysql_select_db($db_name, $this->link_id))
+ error('Unable to select database. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
+ }
+ else
+ error('Unable to connect to MySQL server. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
+
+ // Setup the client-server character set (UTF-8)
+ if (!defined('FORUM_NO_SET_NAMES'))
+ $this->set_names('utf8');
+
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ return;
+ }
+
+
+ function end_transaction()
+ {
+ return;
+ }
+
+
+ function query($sql, $unbuffered = false)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ if ($unbuffered)
+ $this->query_result = @mysql_unbuffered_query($sql, $this->link_id);
+ else
+ $this->query_result = @mysql_query($sql, $this->link_id);
+
+ if ($this->query_result)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ return ($query_id) ? @mysql_result($query_id, $row, $col) : false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @mysql_fetch_row($query_id) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @mysql_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false;
+ }
+
+
+ function insert_id()
+ {
+ return ($this->link_id) ? @mysql_insert_id($this->link_id) : false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ return ($query_id) ? @mysql_free_result($query_id) : false;
+ }
+
+
+ function escape($str)
+ {
+ if (is_array($str))
+ return '';
+ else if (function_exists('mysql_real_escape_string'))
+ return mysql_real_escape_string($str, $this->link_id);
+ else
+ return mysql_escape_string($str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = @mysql_errno($this->link_id);
+ $result['error_msg'] = @mysql_error($this->link_id);
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->query_result)
+ @mysql_free_result($this->query_result);
+
+ return @mysql_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+ function set_names($names)
+ {
+ return $this->query('SET NAMES \''.$this->escape($names).'\'');
+ }
+
+ function get_version()
+ {
+ $result = $this->query('SELECT VERSION()');
+
+ return array(
+ 'name' => 'MySQL Standard',
+ 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
+ );
+ }
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $exists = false;
+
+ $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
+ while ($cur_index = $this->fetch_assoc($result))
+ {
+ if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
+ {
+ $exists = true;
+ break;
+ }
+ }
+
+ return $exists;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ if (isset($field_data['collation']))
+ $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
+
+ if (!$field_data['allow_null'])
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'MyISAM').' CHARACTER SET utf8';
+
+ return $this->query($query) ? true : false;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/dblayer/mysql_innodb.php b/include/dblayer/mysql_innodb.php
new file mode 100644
index 0000000..b78c63c
--- /dev/null
+++ b/include/dblayer/mysql_innodb.php
@@ -0,0 +1,363 @@
+ 'INT(10) UNSIGNED AUTO_INCREMENT'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ $this->prefix = $db_prefix;
+
+ if ($p_connect)
+ $this->link_id = @mysql_pconnect($db_host, $db_username, $db_password);
+ else
+ $this->link_id = @mysql_connect($db_host, $db_username, $db_password);
+
+ if ($this->link_id)
+ {
+ if (!@mysql_select_db($db_name, $this->link_id))
+ error('Unable to select database. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
+ }
+ else
+ error('Unable to connect to MySQL server. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
+
+ // Setup the client-server character set (UTF-8)
+ if (!defined('FORUM_NO_SET_NAMES'))
+ $this->set_names('utf8');
+
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ ++$this->in_transaction;
+
+ mysql_query('START TRANSACTION', $this->link_id);
+ return;
+ }
+
+
+ function end_transaction()
+ {
+ --$this->in_transaction;
+
+ mysql_query('COMMIT', $this->link_id);
+ return;
+ }
+
+
+ function query($sql, $unbuffered = false)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ if ($unbuffered)
+ $this->query_result = @mysql_unbuffered_query($sql, $this->link_id);
+ else
+ $this->query_result = @mysql_query($sql, $this->link_id);
+
+ if ($this->query_result)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ // Rollback transaction
+ if ($this->in_transaction)
+ mysql_query('ROLLBACK', $this->link_id);
+
+ --$this->in_transaction;
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ return ($query_id) ? @mysql_result($query_id, $row, $col) : false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @mysql_fetch_row($query_id) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @mysql_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false;
+ }
+
+
+ function insert_id()
+ {
+ return ($this->link_id) ? @mysql_insert_id($this->link_id) : false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ return ($query_id) ? @mysql_free_result($query_id) : false;
+ }
+
+
+ function escape($str)
+ {
+ if (is_array($str))
+ return '';
+ else if (function_exists('mysql_real_escape_string'))
+ return mysql_real_escape_string($str, $this->link_id);
+ else
+ return mysql_escape_string($str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = @mysql_errno($this->link_id);
+ $result['error_msg'] = @mysql_error($this->link_id);
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->query_result)
+ @mysql_free_result($this->query_result);
+
+ return @mysql_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+
+ function set_names($names)
+ {
+ return $this->query('SET NAMES \''.$this->escape($names).'\'');
+ }
+
+
+ function get_version()
+ {
+ $result = $this->query('SELECT VERSION()');
+
+ return array(
+ 'name' => 'MySQL Standard (InnoDB)',
+ 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
+ );
+ }
+
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $exists = false;
+
+ $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
+ while ($cur_index = $this->fetch_assoc($result))
+ {
+ if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
+ {
+ $exists = true;
+ break;
+ }
+ }
+
+ return $exists;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ if (isset($field_data['collation']))
+ $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
+
+ if (!$field_data['allow_null'])
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'InnoDB').' CHARACTER SET utf8';
+
+ return $this->query($query) ? true : false;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/dblayer/mysqli.php b/include/dblayer/mysqli.php
new file mode 100644
index 0000000..9b81bdd
--- /dev/null
+++ b/include/dblayer/mysqli.php
@@ -0,0 +1,352 @@
+ 'INT(10) UNSIGNED AUTO_INCREMENT'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ $this->prefix = $db_prefix;
+
+ // Was a custom port supplied with $db_host?
+ if (strpos($db_host, ':') !== false)
+ list($db_host, $db_port) = explode(':', $db_host);
+
+ // Persistent connection in MySQLi are only available in PHP 5.3 and later releases
+ $p_connect = $p_connect && version_compare(PHP_VERSION, '5.3.0', '>=') ? 'p:' : '';
+
+ if (isset($db_port))
+ $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name, $db_port);
+ else
+ $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name);
+
+ if (!$this->link_id)
+ error('Unable to connect to MySQL and select database. MySQL reported: '.mysqli_connect_error(), __FILE__, __LINE__);
+
+ // Setup the client-server character set (UTF-8)
+ if (!defined('FORUM_NO_SET_NAMES'))
+ $this->set_names('utf8');
+
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ return;
+ }
+
+
+ function end_transaction()
+ {
+ return;
+ }
+
+
+ function query($sql, $unbuffered = false)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ $this->query_result = @mysqli_query($this->link_id, $sql);
+
+ if ($this->query_result)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ if ($query_id)
+ {
+ if ($row)
+ @mysqli_data_seek($query_id, $row);
+
+ $cur_row = @mysqli_fetch_row($query_id);
+ return $cur_row[$col];
+ }
+ else
+ return false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_fetch_assoc($query_id) : false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_fetch_row($query_id) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->link_id) ? @mysqli_affected_rows($this->link_id) : false;
+ }
+
+
+ function insert_id()
+ {
+ return ($this->link_id) ? @mysqli_insert_id($this->link_id) : false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ return ($query_id) ? @mysqli_free_result($query_id) : false;
+ }
+
+
+ function escape($str)
+ {
+ return is_array($str) ? '' : mysqli_real_escape_string($this->link_id, $str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = @mysqli_errno($this->link_id);
+ $result['error_msg'] = @mysqli_error($this->link_id);
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->query_result)
+ @mysqli_free_result($this->query_result);
+
+ return @mysqli_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+ function set_names($names)
+ {
+ return $this->query('SET NAMES \''.$this->escape($names).'\'');
+ }
+
+
+ function get_version()
+ {
+ $result = $this->query('SELECT VERSION()');
+
+ return array(
+ 'name' => 'MySQL Improved',
+ 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
+ );
+ }
+
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $exists = false;
+
+ $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
+ while ($cur_index = $this->fetch_assoc($result))
+ {
+ if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
+ {
+ $exists = true;
+ break;
+ }
+ }
+
+ return $exists;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ if (isset($field_data['collation']))
+ $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
+
+ if (!$field_data['allow_null'])
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'MyISAM').' CHARACTER SET utf8';
+
+ return $this->query($query) ? true : false;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/dblayer/mysqli_innodb.php b/include/dblayer/mysqli_innodb.php
new file mode 100644
index 0000000..2b591cd
--- /dev/null
+++ b/include/dblayer/mysqli_innodb.php
@@ -0,0 +1,366 @@
+ 'INT(10) UNSIGNED AUTO_INCREMENT'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ $this->prefix = $db_prefix;
+
+ // Was a custom port supplied with $db_host?
+ if (strpos($db_host, ':') !== false)
+ list($db_host, $db_port) = explode(':', $db_host);
+
+ // Persistent connection in MySQLi are only available in PHP 5.3 and later releases
+ $p_connect = $p_connect && version_compare(PHP_VERSION, '5.3.0', '>=') ? 'p:' : '';
+
+ if (isset($db_port))
+ $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name, $db_port);
+ else
+ $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name);
+
+ if (!$this->link_id)
+ error('Unable to connect to MySQL and select database. MySQL reported: '.mysqli_connect_error(), __FILE__, __LINE__);
+
+ // Setup the client-server character set (UTF-8)
+ if (!defined('FORUM_NO_SET_NAMES'))
+ $this->set_names('utf8');
+
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ ++$this->in_transaction;
+
+ mysqli_query($this->link_id, 'START TRANSACTION');
+ return;
+ }
+
+
+ function end_transaction()
+ {
+ --$this->in_transaction;
+
+ mysqli_query($this->link_id, 'COMMIT');
+ return;
+ }
+
+
+ function query($sql, $unbuffered = false)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ $this->query_result = @mysqli_query($this->link_id, $sql);
+
+ if ($this->query_result)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ // Rollback transaction
+ if ($this->in_transaction)
+ mysqli_query($this->link_id, 'ROLLBACK');
+
+ --$this->in_transaction;
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ if ($query_id)
+ {
+ if ($row)
+ @mysqli_data_seek($query_id, $row);
+
+ $cur_row = @mysqli_fetch_row($query_id);
+ return $cur_row[$col];
+ }
+ else
+ return false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_fetch_assoc($query_id) : false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_fetch_row($query_id) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @mysqli_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->link_id) ? @mysqli_affected_rows($this->link_id) : false;
+ }
+
+
+ function insert_id()
+ {
+ return ($this->link_id) ? @mysqli_insert_id($this->link_id) : false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ return ($query_id) ? @mysqli_free_result($query_id) : false;
+ }
+
+
+ function escape($str)
+ {
+ return is_array($str) ? '' : mysqli_real_escape_string($this->link_id, $str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = @mysqli_errno($this->link_id);
+ $result['error_msg'] = @mysqli_error($this->link_id);
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->query_result)
+ @mysqli_free_result($this->query_result);
+
+ return @mysqli_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+
+ function set_names($names)
+ {
+ return $this->query('SET NAMES \''.$this->escape($names).'\'');
+ }
+
+
+ function get_version()
+ {
+ $result = $this->query('SELECT VERSION()');
+
+ return array(
+ 'name' => 'MySQL Improved (InnoDB)',
+ 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
+ );
+ }
+
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $exists = false;
+
+ $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
+ while ($cur_index = $this->fetch_assoc($result))
+ {
+ if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
+ {
+ $exists = true;
+ break;
+ }
+ }
+
+ return $exists;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ if (isset($field_data['collation']))
+ $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
+
+ if (!$field_data['allow_null'])
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'InnoDB').' CHARACTER SET utf8';
+
+ return $this->query($query) ? true : false;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/dblayer/pgsql.php b/include/dblayer/pgsql.php
new file mode 100644
index 0000000..05d8cf0
--- /dev/null
+++ b/include/dblayer/pgsql.php
@@ -0,0 +1,427 @@
+ 'SMALLINT',
+ '/^(MEDIUM)?INT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'INTEGER',
+ '/^BIGINT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'BIGINT',
+ '/^(TINY|MEDIUM|LONG)?TEXT$/i' => 'TEXT',
+ '/^DOUBLE( )?(\\([0-9,]+\\))?( )?(UNSIGNED)?$/i' => 'DOUBLE PRECISION',
+ '/^FLOAT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'REAL'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ $this->prefix = $db_prefix;
+
+ if ($db_host)
+ {
+ if (strpos($db_host, ':') !== false)
+ {
+ list($db_host, $dbport) = explode(':', $db_host);
+ $connect_str[] = 'host='.$db_host.' port='.$dbport;
+ }
+ else
+ $connect_str[] = 'host='.$db_host;
+ }
+
+ if ($db_name)
+ $connect_str[] = 'dbname='.$db_name;
+
+ if ($db_username)
+ $connect_str[] = 'user='.$db_username;
+
+ if ($db_password)
+ $connect_str[] = 'password='.$db_password;
+
+ if ($p_connect)
+ $this->link_id = @pg_pconnect(implode(' ', $connect_str));
+ else
+ $this->link_id = @pg_connect(implode(' ', $connect_str));
+
+ if (!$this->link_id)
+ error('Unable to connect to PostgreSQL server', __FILE__, __LINE__);
+
+ // Setup the client-server character set (UTF-8)
+ if (!defined('FORUM_NO_SET_NAMES'))
+ $this->set_names('utf8');
+
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ ++$this->in_transaction;
+
+ return (@pg_query($this->link_id, 'BEGIN')) ? true : false;
+ }
+
+
+ function end_transaction()
+ {
+ --$this->in_transaction;
+
+ if (@pg_query($this->link_id, 'COMMIT'))
+ return true;
+ else
+ {
+ @pg_query($this->link_id, 'ROLLBACK');
+ return false;
+ }
+ }
+
+
+ function query($sql, $unbuffered = false) // $unbuffered is ignored since there is no pgsql_unbuffered_query()
+ {
+ if (strrpos($sql, 'LIMIT') !== false)
+ $sql = preg_replace('#LIMIT ([0-9]+),([ 0-9]+)#', 'LIMIT \\2 OFFSET \\1', $sql);
+
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ @pg_send_query($this->link_id, $sql);
+ $this->query_result = @pg_get_result($this->link_id);
+
+ if (pg_result_status($this->query_result) != PGSQL_FATAL_ERROR)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ $this->last_query_text[$this->query_result] = $sql;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ $this->error_msg = @pg_result_error($this->query_result);
+
+ if ($this->in_transaction)
+ @pg_query($this->link_id, 'ROLLBACK');
+
+ --$this->in_transaction;
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ return ($query_id) ? @pg_fetch_result($query_id, $row, $col) : false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ return ($query_id) ? @pg_fetch_assoc($query_id) : false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @pg_fetch_row($query_id) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @pg_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->query_result) ? @pg_affected_rows($this->query_result) : false;
+ }
+
+
+ function insert_id()
+ {
+ $query_id = $this->query_result;
+
+ if ($query_id && $this->last_query_text[$query_id] != '')
+ {
+ if (preg_match('/^INSERT INTO ([a-z0-9\_\-]+)/is', $this->last_query_text[$query_id], $table_name))
+ {
+ // Hack (don't ask)
+ if (substr($table_name[1], -6) == 'groups')
+ $table_name[1] .= '_g';
+
+ $temp_q_id = @pg_query($this->link_id, 'SELECT currval(\''.$table_name[1].'_id_seq\')');
+ return ($temp_q_id) ? intval(@pg_fetch_result($temp_q_id, 0)) : false;
+ }
+ }
+
+ return false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ if (!$query_id)
+ $query_id = $this->query_result;
+
+ return ($query_id) ? @pg_free_result($query_id) : false;
+ }
+
+
+ function escape($str)
+ {
+ return is_array($str) ? '' : pg_escape_string($str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = false;
+/*
+ if (!empty($this->query_result))
+ {
+ $result['error_msg'] = trim(@pg_result_error($this->query_result));
+ if ($result['error_msg'] != '')
+ return $result;
+ }
+
+ $result['error_msg'] = (!empty($this->link_id)) ? trim(@pg_last_error($this->link_id)) : trim(@pg_last_error());
+*/
+ $result['error_msg'] = $this->error_msg;
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->in_transaction)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array('COMMIT', 0);
+
+ @pg_query($this->link_id, 'COMMIT');
+ }
+
+ if ($this->query_result)
+ @pg_free_result($this->query_result);
+
+ return @pg_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+ function set_names($names)
+ {
+ return $this->query('SET NAMES \''.$this->escape($names).'\'');
+ }
+
+
+ function get_version()
+ {
+ $result = $this->query('SELECT VERSION()');
+
+ return array(
+ 'name' => 'PostgreSQL',
+ 'version' => preg_replace('/^[^0-9]+([^\s,-]+).*$/', '\\1', $this->result($result))
+ );
+ }
+
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT 1 FROM pg_class WHERE relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT 1 FROM pg_class c INNER JOIN pg_attribute a ON a.attrelid = c.oid WHERE c.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND a.attname = \''.$this->escape($field_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT 1 FROM pg_index i INNER JOIN pg_class c1 ON c1.oid = i.indrelid INNER JOIN pg_class c2 ON c2.oid = i.indexrelid WHERE c1.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND c2.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_'.$this->escape($index_name).'\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ // The SERIAL datatype is a special case where we don't need to say not null
+ if (!$field_data['allow_null'] && $field_data['datatype'] != 'SERIAL')
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE ('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".')';
+
+ $result = $this->query($query) ? true : false;
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $result &= $this->add_index($table_name, $index_name, $index_fields, false, $no_prefix);
+ }
+
+ return $result;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ $result = $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type) ? true : false;
+
+ if ($default_value !== null)
+ {
+ if (!is_int($default_value) && !is_float($default_value))
+ $default_value = '\''.$this->escape($default_value).'\'';
+
+ $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ALTER '.$field_name.' SET DEFAULT '.$default_value) ? true : false;
+ $result &= $this->query('UPDATE '.($no_prefix ? '' : $this->prefix).$table_name.' SET '.$field_name.'='.$default_value) ? true : false;
+ }
+
+ if (!$allow_null)
+ $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ALTER '.$field_name.' SET NOT NULL') ? true : false;
+
+ return $result;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+
+ $result = $this->add_field($table_name, 'tmp_'.$field_name, $field_type, $allow_null, $default_value, $after_field, $no_prefix);
+ $result &= $this->query('UPDATE '.($no_prefix ? '' : $this->prefix).$table_name.' SET tmp_'.$field_name.' = '.$field_name) ? true : false;
+ $result &= $this->drop_field($table_name, $field_name, $no_prefix);
+ $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' RENAME COLUMN tmp_'.$field_name.' TO '.$field_name) ? true : false;
+
+ return $result;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('CREATE '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ON '.($no_prefix ? '' : $this->prefix).$table_name.'('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('DELETE FROM '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/dblayer/sqlite.php b/include/dblayer/sqlite.php
new file mode 100644
index 0000000..49ffeb8
--- /dev/null
+++ b/include/dblayer/sqlite.php
@@ -0,0 +1,528 @@
+ 'INTEGER',
+ '/^(TINY|SMALL|MEDIUM|BIG)?INT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'INTEGER',
+ '/^(TINY|MEDIUM|LONG)?TEXT$/i' => 'TEXT'
+ );
+
+
+ function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
+ {
+ // Prepend $db_name with the path to the forum root directory
+ $db_name = PUN_ROOT.$db_name;
+
+ $this->prefix = $db_prefix;
+
+ if (!file_exists($db_name))
+ {
+ @touch($db_name);
+ @chmod($db_name, 0666);
+ if (!file_exists($db_name))
+ error('Unable to create new database \''.$db_name.'\'. Permission denied', __FILE__, __LINE__);
+ }
+
+ if (!is_readable($db_name))
+ error('Unable to open database \''.$db_name.'\' for reading. Permission denied', __FILE__, __LINE__);
+
+ if (!is_writable($db_name))
+ error('Unable to open database \''.$db_name.'\' for writing. Permission denied', __FILE__, __LINE__);
+
+ if ($p_connect)
+ $this->link_id = @sqlite_popen($db_name, 0666, $sqlite_error);
+ else
+ $this->link_id = @sqlite_open($db_name, 0666, $sqlite_error);
+
+ if (!$this->link_id)
+ error('Unable to open database \''.$db_name.'\'. SQLite reported: '.$sqlite_error, __FILE__, __LINE__);
+ else
+ return $this->link_id;
+ }
+
+
+ function start_transaction()
+ {
+ ++$this->in_transaction;
+
+ return (@sqlite_query($this->link_id, 'BEGIN')) ? true : false;
+ }
+
+
+ function end_transaction()
+ {
+ --$this->in_transaction;
+
+ if (@sqlite_query($this->link_id, 'COMMIT'))
+ return true;
+ else
+ {
+ @sqlite_query($this->link_id, 'ROLLBACK');
+ return false;
+ }
+ }
+
+
+ function query($sql, $unbuffered = false)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $q_start = get_microtime();
+
+ if ($unbuffered)
+ $this->query_result = @sqlite_unbuffered_query($this->link_id, $sql);
+ else
+ $this->query_result = @sqlite_query($this->link_id, $sql);
+
+ if ($this->query_result)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
+
+ ++$this->num_queries;
+
+ return $this->query_result;
+ }
+ else
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array($sql, 0);
+
+ $this->error_no = @sqlite_last_error($this->link_id);
+ $this->error_msg = @sqlite_error_string($this->error_no);
+
+ if ($this->in_transaction)
+ @sqlite_query($this->link_id, 'ROLLBACK');
+
+ --$this->in_transaction;
+
+ return false;
+ }
+ }
+
+
+ function result($query_id = 0, $row = 0, $col = 0)
+ {
+ if ($query_id)
+ {
+ if ($row != 0)
+ @sqlite_seek($query_id, $row);
+
+ $cur_row = @sqlite_current($query_id);
+ return $cur_row[$col];
+ }
+ else
+ return false;
+ }
+
+
+ function fetch_assoc($query_id = 0)
+ {
+ if ($query_id)
+ {
+ $cur_row = @sqlite_fetch_array($query_id, SQLITE_ASSOC);
+ if ($cur_row)
+ {
+ // Horrible hack to get rid of table names and table aliases from the array keys
+ foreach ($cur_row as $key => $value)
+ {
+ $dot_spot = strpos($key, '.');
+ if ($dot_spot !== false)
+ {
+ unset($cur_row[$key]);
+ $key = substr($key, $dot_spot+1);
+ $cur_row[$key] = $value;
+ }
+ }
+ }
+
+ return $cur_row;
+ }
+ else
+ return false;
+ }
+
+
+ function fetch_row($query_id = 0)
+ {
+ return ($query_id) ? @sqlite_fetch_array($query_id, SQLITE_NUM) : false;
+ }
+
+
+ function num_rows($query_id = 0)
+ {
+ return ($query_id) ? @sqlite_num_rows($query_id) : false;
+ }
+
+
+ function affected_rows()
+ {
+ return ($this->query_result) ? @sqlite_changes($this->query_result) : false;
+ }
+
+
+ function insert_id()
+ {
+ return ($this->link_id) ? @sqlite_last_insert_rowid($this->link_id) : false;
+ }
+
+
+ function get_num_queries()
+ {
+ return $this->num_queries;
+ }
+
+
+ function get_saved_queries()
+ {
+ return $this->saved_queries;
+ }
+
+
+ function free_result($query_id = false)
+ {
+ return true;
+ }
+
+
+ function escape($str)
+ {
+ return is_array($str) ? '' : sqlite_escape_string($str);
+ }
+
+
+ function error()
+ {
+ $result['error_sql'] = @current(@end($this->saved_queries));
+ $result['error_no'] = $this->error_no;
+ $result['error_msg'] = $this->error_msg;
+
+ return $result;
+ }
+
+
+ function close()
+ {
+ if ($this->link_id)
+ {
+ if ($this->in_transaction)
+ {
+ if (defined('PUN_SHOW_QUERIES'))
+ $this->saved_queries[] = array('COMMIT', 0);
+
+ @sqlite_query($this->link_id, 'COMMIT');
+ }
+
+ return @sqlite_close($this->link_id);
+ }
+ else
+ return false;
+ }
+
+ function set_names($names)
+ {
+ return;
+ }
+
+
+ function get_version()
+ {
+ return array(
+ 'name' => 'SQLite',
+ 'version' => sqlite_libversion()
+ );
+ }
+
+
+ function table_exists($table_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT 1 FROM sqlite_master WHERE name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND type=\'table\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function field_exists($table_name, $field_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT sql FROM sqlite_master WHERE name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND type=\'table\'');
+ if (!$this->num_rows($result))
+ return false;
+
+ return preg_match('/[\r\n]'.preg_quote($field_name).' /', $this->result($result));
+ }
+
+
+ function index_exists($table_name, $index_name, $no_prefix = false)
+ {
+ $result = $this->query('SELECT 1 FROM sqlite_master WHERE tbl_name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_'.$this->escape($index_name).'\' AND type=\'index\'');
+ return $this->num_rows($result) > 0;
+ }
+
+
+ function create_table($table_name, $schema, $no_prefix = false)
+ {
+ if ($this->table_exists($table_name, $no_prefix))
+ return true;
+
+ $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
+
+ // Go through every schema element and add it to the query
+ foreach ($schema['FIELDS'] as $field_name => $field_data)
+ {
+ $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
+
+ $query .= $field_name.' '.$field_data['datatype'];
+
+ if (!$field_data['allow_null'])
+ $query .= ' NOT NULL';
+
+ if (isset($field_data['default']))
+ $query .= ' DEFAULT '.$field_data['default'];
+
+ $query .= ",\n";
+ }
+
+ // If we have a primary key, add it
+ if (isset($schema['PRIMARY KEY']))
+ $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
+
+ // Add unique keys
+ if (isset($schema['UNIQUE KEYS']))
+ {
+ foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
+ $query .= 'UNIQUE ('.implode(',', $key_fields).'),'."\n";
+ }
+
+ // We remove the last two characters (a newline and a comma) and add on the ending
+ $query = substr($query, 0, strlen($query) - 2)."\n".')';
+
+ $result = $this->query($query) ? true : false;
+
+ // Add indexes
+ if (isset($schema['INDEXES']))
+ {
+ foreach ($schema['INDEXES'] as $index_name => $index_fields)
+ $result &= $this->add_index($table_name, $index_name, $index_fields, false, $no_prefix);
+ }
+
+ return $result;
+ }
+
+
+ function drop_table($table_name, $no_prefix = false)
+ {
+ if (!$this->table_exists($table_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+
+
+ function get_table_info($table_name, $no_prefix = false)
+ {
+ // Grab table info
+ $result = $this->query('SELECT sql FROM sqlite_master WHERE tbl_name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' ORDER BY type DESC') or error('Unable to fetch table information', __FILE__, __LINE__, $this->error());
+ $num_rows = $this->num_rows($result);
+
+ if ($num_rows == 0)
+ return;
+
+ $table = array();
+ $table['indices'] = array();
+ while ($cur_index = $this->fetch_assoc($result))
+ {
+ if (empty($cur_index['sql']))
+ continue;
+
+ if (!isset($table['sql']))
+ $table['sql'] = $cur_index['sql'];
+ else
+ $table['indices'][] = $cur_index['sql'];
+ }
+
+ // Work out the columns in the table currently
+ $table_lines = explode("\n", $table['sql']);
+ $table['columns'] = array();
+ foreach ($table_lines as $table_line)
+ {
+ $table_line = pun_trim($table_line);
+ if (substr($table_line, 0, 12) == 'CREATE TABLE')
+ continue;
+ else if (substr($table_line, 0, 11) == 'PRIMARY KEY')
+ $table['primary_key'] = $table_line;
+ else if (substr($table_line, 0, 6) == 'UNIQUE')
+ $table['unique'] = $table_line;
+ else if (substr($table_line, 0, strpos($table_line, ' ')) != '')
+ $table['columns'][substr($table_line, 0, strpos($table_line, ' '))] = pun_trim(substr($table_line, strpos($table_line, ' ')));
+ }
+
+ return $table;
+ }
+
+
+ function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = 0, $no_prefix = false)
+ {
+ if ($this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $table = $this->get_table_info($table_name, $no_prefix);
+
+ // Create temp table
+ $now = time();
+ $tmptable = str_replace('CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (', 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' (', $table['sql']);
+ $result = $this->query($tmptable) ? true : false;
+ $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name)) ? true : false;
+
+ // Create new table sql
+ $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
+ $query = $field_type;
+ if (!$allow_null)
+ $query .= ' NOT NULL';
+ if ($default_value === null || $default_value === '')
+ $default_value = '\'\'';
+
+ $query .= ' DEFAULT '.$default_value;
+
+ $old_columns = array_keys($table['columns']);
+ array_insert($table['columns'], $after_field, $query.',', $field_name);
+
+ $new_table = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (';
+
+ foreach ($table['columns'] as $cur_column => $column_details)
+ $new_table .= "\n".$cur_column.' '.$column_details;
+
+ if (isset($table['unique']))
+ $new_table .= "\n".$table['unique'].',';
+
+ if (isset($table['primary_key']))
+ $new_table .= "\n".$table['primary_key'];
+
+ $new_table = trim($new_table, ',')."\n".');';
+
+ // Drop old table
+ $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name));
+
+ // Create new table
+ $result &= $this->query($new_table) ? true : false;
+
+ // Recreate indexes
+ if (!empty($table['indices']))
+ {
+ foreach ($table['indices'] as $cur_index)
+ $result &= $this->query($cur_index) ? true : false;
+ }
+
+ // Copy content back
+ $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' ('.implode(', ', $old_columns).') SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now) ? true : false;
+
+ // Drop temp table
+ $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now);
+
+ return $result;
+ }
+
+
+ function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = 0, $no_prefix = false)
+ {
+ // Unneeded for SQLite
+ return true;
+ }
+
+
+ function drop_field($table_name, $field_name, $no_prefix = false)
+ {
+ if (!$this->field_exists($table_name, $field_name, $no_prefix))
+ return true;
+
+ $table = $this->get_table_info($table_name, $no_prefix);
+
+ // Create temp table
+ $now = time();
+ $tmptable = str_replace('CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (', 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' (', $table['sql']);
+ $result = $this->query($tmptable) ? true : false;
+ $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name)) ? true : false;
+
+ // Work out the columns we need to keep and the sql for the new table
+ unset($table['columns'][$field_name]);
+ $new_columns = array_keys($table['columns']);
+
+ $new_table = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (';
+
+ foreach ($table['columns'] as $cur_column => $column_details)
+ $new_table .= "\n".$cur_column.' '.$column_details;
+
+ if (isset($table['unique']))
+ $new_table .= "\n".$table['unique'].',';
+
+ if (isset($table['primary_key']))
+ $new_table .= "\n".$table['primary_key'];
+
+ $new_table = trim($new_table, ',')."\n".');';
+
+ // Drop old table
+ $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name));
+
+ // Create new table
+ $result &= $this->query($new_table) ? true : false;
+
+ // Recreate indexes
+ if (!empty($table['indices']))
+ {
+ foreach ($table['indices'] as $cur_index)
+ if (!preg_match('%\('.preg_quote($field_name, '%').'\)%', $cur_index))
+ $result &= $this->query($cur_index) ? true : false;
+ }
+
+ // Copy content back
+ $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' SELECT '.implode(', ', $new_columns).' FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now) ? true : false;
+
+ // Drop temp table
+ $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now);
+
+ return $result;
+ }
+
+
+ function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
+ {
+ if ($this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('CREATE '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ON '.($no_prefix ? '' : $this->prefix).$table_name.'('.implode(',', $index_fields).')') ? true : false;
+ }
+
+
+ function drop_index($table_name, $index_name, $no_prefix = false)
+ {
+ if (!$this->index_exists($table_name, $index_name, $no_prefix))
+ return true;
+
+ return $this->query('DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
+ }
+
+ function truncate_table($table_name, $no_prefix = false)
+ {
+ return $this->query('DELETE FROM '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
+ }
+}
diff --git a/include/email.php b/include/email.php
new file mode 100644
index 0000000..86f0660
--- /dev/null
+++ b/include/email.php
@@ -0,0 +1,186 @@
+ 80)
+ return false;
+
+ return preg_match('/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|("[^"]+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\d\-]+\.)+[a-zA-Z]{2,}))$/', $email);
+}
+
+
+//
+// Check if $email is banned
+//
+function is_banned_email($email)
+{
+ global $pun_bans;
+
+ foreach ($pun_bans as $cur_ban)
+ {
+ if ($cur_ban['email'] != '' &&
+ ($email == $cur_ban['email'] ||
+ (strpos($cur_ban['email'], '@') === false && stristr($email, '@'.$cur_ban['email']))))
+ return true;
+ }
+
+ return false;
+}
+
+
+//
+// Wrapper for PHP's mail()
+//
+function pun_mail($to, $subject, $message, $reply_to_email = '', $reply_to_name = '')
+{
+ global $pun_config, $lang_common;
+
+ // Default sender/return address
+ $from_name = str_replace('"', '', $pun_config['o_board_title'].' '.$lang_common['Mailer']);
+ $from_email = $pun_config['o_webmaster_email'];
+
+ // Do a little spring cleaning
+ $to = pun_trim(preg_replace('#[\n\r]+#s', '', $to));
+ $subject = pun_trim(preg_replace('#[\n\r]+#s', '', $subject));
+ $from_email = pun_trim(preg_replace('#[\n\r:]+#s', '', $from_email));
+ $from_name = pun_trim(preg_replace('#[\n\r:]+#s', '', str_replace('"', '', $from_name)));
+ $reply_to_email = pun_trim(preg_replace('#[\n\r:]+#s', '', $reply_to_email));
+ $reply_to_name = pun_trim(preg_replace('#[\n\r:]+#s', '', str_replace('"', '', $reply_to_name)));
+
+ // Set up some headers to take advantage of UTF-8
+ $from = "=?UTF-8?B?".base64_encode($from_name)."?=".' <'.$from_email.'>';
+ $subject = "=?UTF-8?B?".base64_encode($subject)."?=";
+
+ $headers = 'From: '.$from."\r\n".'Date: '.gmdate('r')."\r\n".'MIME-Version: 1.0'."\r\n".'Content-transfer-encoding: 8bit'."\r\n".'Content-type: text/plain; charset=utf-8'."\r\n".'X-Mailer: FluxBB Mailer';
+
+ // If we specified a reply-to email, we deal with it here
+ if (!empty($reply_to_email))
+ {
+ $reply_to = "=?UTF-8?B?".base64_encode($reply_to_name)."?=".' <'.$reply_to_email.'>';
+
+ $headers .= "\r\n".'Reply-To: '.$reply_to;
+ }
+
+ // Make sure all linebreaks are CRLF in message (and strip out any NULL bytes)
+ $message = str_replace(array("\n", "\0"), array("\r\n", ''), pun_linebreaks($message));
+
+ if ($pun_config['o_smtp_host'] != '')
+ smtp_mail($to, $subject, $message, $headers);
+ else
+ {
+ // Change the linebreaks used in the headers according to OS
+ if (strtoupper(substr(PHP_OS, 0, 3)) == 'MAC')
+ $headers = str_replace("\r\n", "\r", $headers);
+ else if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN')
+ $headers = str_replace("\r\n", "\n", $headers);
+
+ mail($to, $subject, $message, $headers);
+ }
+}
+
+
+//
+// This function was originally a part of the phpBB Group forum software phpBB2 (http://www.phpbb.com)
+// They deserve all the credit for writing it. I made small modifications for it to suit PunBB and it's coding standards
+//
+function server_parse($socket, $expected_response)
+{
+ $server_response = '';
+ while (substr($server_response, 3, 1) != ' ')
+ {
+ if (!($server_response = fgets($socket, 256)))
+ error('Couldn\'t get mail server response codes. Please contact the forum administrator.', __FILE__, __LINE__);
+ }
+
+ if (!(substr($server_response, 0, 3) == $expected_response))
+ error('Unable to send email. Please contact the forum administrator with the following error message reported by the SMTP server: "'.$server_response.'"', __FILE__, __LINE__);
+}
+
+
+//
+// This function was originally a part of the phpBB Group forum software phpBB2 (http://www.phpbb.com)
+// They deserve all the credit for writing it. I made small modifications for it to suit PunBB and it's coding standards.
+//
+function smtp_mail($to, $subject, $message, $headers = '')
+{
+ global $pun_config;
+
+ $recipients = explode(',', $to);
+
+ // Sanitize the message
+ $message = str_replace("\r\n.", "\r\n..", $message);
+ $message = (substr($message, 0, 1) == '.' ? '.'.$message : $message);
+
+ // Are we using port 25 or a custom port?
+ if (strpos($pun_config['o_smtp_host'], ':') !== false)
+ list($smtp_host, $smtp_port) = explode(':', $pun_config['o_smtp_host']);
+ else
+ {
+ $smtp_host = $pun_config['o_smtp_host'];
+ $smtp_port = 25;
+ }
+
+ if ($pun_config['o_smtp_ssl'] == '1')
+ $smtp_host = 'ssl://'.$smtp_host;
+
+ if (!($socket = fsockopen($smtp_host, $smtp_port, $errno, $errstr, 15)))
+ error('Could not connect to smtp host "'.$pun_config['o_smtp_host'].'" ('.$errno.') ('.$errstr.')', __FILE__, __LINE__);
+
+ server_parse($socket, '220');
+
+ if ($pun_config['o_smtp_user'] != '' && $pun_config['o_smtp_pass'] != '')
+ {
+ fwrite($socket, 'EHLO '.$smtp_host."\r\n");
+ server_parse($socket, '250');
+
+ fwrite($socket, 'AUTH LOGIN'."\r\n");
+ server_parse($socket, '334');
+
+ fwrite($socket, base64_encode($pun_config['o_smtp_user'])."\r\n");
+ server_parse($socket, '334');
+
+ fwrite($socket, base64_encode($pun_config['o_smtp_pass'])."\r\n");
+ server_parse($socket, '235');
+ }
+ else
+ {
+ fwrite($socket, 'HELO '.$smtp_host."\r\n");
+ server_parse($socket, '250');
+ }
+
+ fwrite($socket, 'MAIL FROM: <'.$pun_config['o_webmaster_email'].'>'."\r\n");
+ server_parse($socket, '250');
+
+ foreach ($recipients as $email)
+ {
+ fwrite($socket, 'RCPT TO: <'.$email.'>'."\r\n");
+ server_parse($socket, '250');
+ }
+
+ fwrite($socket, 'DATA'."\r\n");
+ server_parse($socket, '354');
+
+ fwrite($socket, 'Subject: '.$subject."\r\n".'To: <'.implode('>, <', $recipients).'>'."\r\n".$headers."\r\n\r\n".$message."\r\n");
+
+ fwrite($socket, '.'."\r\n");
+ server_parse($socket, '250');
+
+ fwrite($socket, 'QUIT'."\r\n");
+ fclose($socket);
+
+ return true;
+}
diff --git a/include/functions.php b/include/functions.php
new file mode 100644
index 0000000..054e1ed
--- /dev/null
+++ b/include/functions.php
@@ -0,0 +1,1748 @@
+ 1, 'password_hash' => 'Guest');
+
+ // If a cookie is set, we get the user_id and password hash from it
+ if (isset($_COOKIE[$cookie_name]))
+ list($cookie['user_id'], $cookie['password_hash'], $cookie['expiration_time']) = @unserialize($_COOKIE[$cookie_name]);
+
+ if ($cookie['user_id'] > 1)
+ {
+ // Check if there's a user with the user ID and password hash from the cookie
+ $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($cookie['user_id'])) or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
+ $pun_user = $db->fetch_assoc($result);
+
+ // If user authorisation failed
+ if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) !== $cookie['password_hash'])
+ {
+ $expire = $now + 31536000; // The cookie expires after a year
+ pun_setcookie(1, md5(uniqid(rand(), true)), $expire);
+ set_default_user();
+
+ return;
+ }
+
+ // Send a new, updated cookie with a new expiration timestamp
+ $expire = (intval($cookie['expiration_time']) > $now + $pun_config['o_timeout_visit']) ? $now + 1209600 : $now + $pun_config['o_timeout_visit'];
+ pun_setcookie($pun_user['id'], $pun_user['password'], $expire);
+
+ // Set a default language if the user selected language no longer exists
+ if (!file_exists(PUN_ROOT.'lang/'.$pun_user['language']))
+ $pun_user['language'] = $pun_config['o_default_lang'];
+
+ // Set a default style if the user selected style no longer exists
+ if (!file_exists(PUN_ROOT.'style/'.$pun_user['style'].'.css'))
+ $pun_user['style'] = $pun_config['o_default_style'];
+
+ if (!$pun_user['disp_topics'])
+ $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
+ if (!$pun_user['disp_posts'])
+ $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
+
+ // Define this if you want this visit to affect the online list and the users last visit data
+ if (!defined('PUN_QUIET_VISIT'))
+ {
+ // Update the online list
+ if (!$pun_user['logged'])
+ {
+ $pun_user['logged'] = $now;
+
+ // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table
+ switch ($db_type)
+ {
+ case 'mysql':
+ case 'mysqli':
+ case 'mysql_innodb':
+ case 'mysqli_innodb':
+ case 'sqlite':
+ $db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+ break;
+
+ default:
+ $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT '.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE user_id='.$pun_user['id'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+ break;
+ }
+
+ // Reset tracked topics
+ set_tracked_topics(null);
+ }
+ else
+ {
+ // Special case: We've timed out, but no other user has browsed the forums since we timed out
+ if ($pun_user['logged'] < ($now-$pun_config['o_timeout_visit']))
+ {
+ $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
+ $pun_user['last_visit'] = $pun_user['logged'];
+ }
+
+ $idle_sql = ($pun_user['idle'] == '1') ? ', idle=0' : '';
+ $db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Unable to update online list', __FILE__, __LINE__, $db->error());
+
+ // Update tracked topics with the current expire time
+ if (isset($_COOKIE[$cookie_name.'_track']))
+ forum_setcookie($cookie_name.'_track', $_COOKIE[$cookie_name.'_track'], $now + $pun_config['o_timeout_visit']);
+ }
+ }
+ else
+ {
+ if (!$pun_user['logged'])
+ $pun_user['logged'] = $pun_user['last_visit'];
+ }
+
+ $pun_user['is_guest'] = false;
+ $pun_user['is_admmod'] = $pun_user['g_id'] == PUN_ADMIN || $pun_user['g_moderator'] == '1';
+ }
+ else
+ set_default_user();
+}
+
+
+//
+// Converts the CDATA end sequence ]]> into ]]>
+//
+function escape_cdata($str)
+{
+ return str_replace(']]>', ']]>', $str);
+}
+
+
+//
+// Authenticates the provided username and password against the user database
+// $user can be either a user ID (integer) or a username (string)
+// $password can be either a plaintext password or a password hash including salt ($password_is_hash must be set accordingly)
+//
+function authenticate_user($user, $password, $password_is_hash = false)
+{
+ global $db, $pun_user;
+
+ // Check if there's a user matching $user and $password
+ $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE '.(is_int($user) ? 'u.id='.intval($user) : 'u.username=\''.$db->escape($user).'\'')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+ $pun_user = $db->fetch_assoc($result);
+
+ if (!isset($pun_user['id']) ||
+ ($password_is_hash && $password != $pun_user['password']) ||
+ (!$password_is_hash && pun_hash($password) != $pun_user['password']))
+ set_default_user();
+ else
+ $pun_user['is_guest'] = false;
+}
+
+
+//
+// Try to determine the current URL
+//
+function get_current_url($max_length = 0)
+{
+ $protocol = (!isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off') ? 'http://' : 'https://';
+ $port = (isset($_SERVER['SERVER_PORT']) && (($_SERVER['SERVER_PORT'] != '80' && $protocol == 'http://') || ($_SERVER['SERVER_PORT'] != '443' && $protocol == 'https://')) && strpos($_SERVER['HTTP_HOST'], ':') === false) ? ':'.$_SERVER['SERVER_PORT'] : '';
+
+ $url = urldecode($protocol.$_SERVER['HTTP_HOST'].$port.$_SERVER['REQUEST_URI']);
+
+ if (strlen($url) <= $max_length || $max_length == 0)
+ return $url;
+
+ // We can't find a short enough url
+ return null;
+}
+
+
+//
+// Fill $pun_user with default values (for guests)
+//
+function set_default_user()
+{
+ global $db, $db_type, $pun_user, $pun_config;
+
+ $remote_addr = get_remote_address();
+
+ // Fetch guest user
+ $result = $db->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.ident=\''.$remote_addr.'\' WHERE u.id=1') or error('Unable to fetch guest information', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ exit('Unable to fetch guest information. The table \''.$db->prefix.'users\' must contain an entry with id = 1 that represents anonymous users.');
+
+ $pun_user = $db->fetch_assoc($result);
+
+ // Update online list
+ if (!$pun_user['logged'])
+ {
+ $pun_user['logged'] = time();
+
+ // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table
+ switch ($db_type)
+ {
+ case 'mysql':
+ case 'mysqli':
+ case 'mysql_innodb':
+ case 'mysqli_innodb':
+ case 'sqlite':
+ $db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+ break;
+
+ default:
+ $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT 1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($remote_addr).'\')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+ break;
+ }
+ }
+ else
+ $db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error());
+
+ $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
+ $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
+ $pun_user['timezone'] = $pun_config['o_default_timezone'];
+ $pun_user['dst'] = $pun_config['o_default_dst'];
+ $pun_user['language'] = $pun_config['o_default_lang'];
+ $pun_user['style'] = $pun_config['o_default_style'];
+ $pun_user['is_guest'] = true;
+ $pun_user['is_admmod'] = false;
+}
+
+
+//
+// Set a cookie, FluxBB style!
+// Wrapper for forum_setcookie
+//
+function pun_setcookie($user_id, $password_hash, $expire)
+{
+ global $cookie_name, $cookie_seed;
+
+ forum_setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash), $expire)), $expire);
+}
+
+
+//
+// Set a cookie, FluxBB style!
+//
+function forum_setcookie($name, $value, $expire)
+{
+ global $cookie_path, $cookie_domain, $cookie_secure;
+
+ // Enable sending of a P3P header
+ header('P3P: CP="CUR ADM"');
+
+ if (version_compare(PHP_VERSION, '5.2.0', '>='))
+ setcookie($name, $value, $expire, $cookie_path, $cookie_domain, $cookie_secure, true);
+ else
+ setcookie($name, $value, $expire, $cookie_path.'; HttpOnly', $cookie_domain, $cookie_secure);
+}
+
+
+//
+// Check whether the connecting user is banned (and delete any expired bans while we're at it)
+//
+function check_bans()
+{
+ global $db, $pun_config, $lang_common, $pun_user, $pun_bans;
+
+ // Admins aren't affected
+ if ($pun_user['g_id'] == PUN_ADMIN || !$pun_bans)
+ return;
+
+ // Add a dot or a colon (depending on IPv4/IPv6) at the end of the IP address to prevent banned address
+ // 192.168.0.5 from matching e.g. 192.168.0.50
+ $user_ip = get_remote_address();
+ $user_ip .= (strpos($user_ip, '.') !== false) ? '.' : ':';
+
+ $bans_altered = false;
+ $is_banned = false;
+
+ foreach ($pun_bans as $cur_ban)
+ {
+ // Has this ban expired?
+ if ($cur_ban['expire'] != '' && $cur_ban['expire'] <= time())
+ {
+ $db->query('DELETE FROM '.$db->prefix.'bans WHERE id='.$cur_ban['id']) or error('Unable to delete expired ban', __FILE__, __LINE__, $db->error());
+ $bans_altered = true;
+ continue;
+ }
+
+ if ($cur_ban['username'] != '' && utf8_strtolower($pun_user['username']) == utf8_strtolower($cur_ban['username']))
+ $is_banned = true;
+
+ if ($cur_ban['ip'] != '')
+ {
+ $cur_ban_ips = explode(' ', $cur_ban['ip']);
+
+ $num_ips = count($cur_ban_ips);
+ for ($i = 0; $i < $num_ips; ++$i)
+ {
+ // Add the proper ending to the ban
+ if (strpos($user_ip, '.') !== false)
+ $cur_ban_ips[$i] = $cur_ban_ips[$i].'.';
+ else
+ $cur_ban_ips[$i] = $cur_ban_ips[$i].':';
+
+ if (substr($user_ip, 0, strlen($cur_ban_ips[$i])) == $cur_ban_ips[$i])
+ {
+ $is_banned = true;
+ break;
+ }
+ }
+ }
+
+ if ($is_banned)
+ {
+ $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+ message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'
'.pun_htmlspecialchars($cur_ban['message']).'
' : '
').$lang_common['Ban message 4'].' '.$pun_config['o_admin_email'].'.', true);
+ }
+ }
+
+ // If we removed any expired bans during our run-through, we need to regenerate the bans cache
+ if ($bans_altered)
+ {
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_bans_cache();
+ }
+}
+
+
+//
+// Check username
+//
+function check_username($username, $exclude_id = null)
+{
+ global $db, $pun_config, $errors, $lang_prof_reg, $lang_register, $lang_common, $pun_bans;
+
+ // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames)
+ $username = preg_replace('#\s+#s', ' ', $username);
+
+ // Validate username
+ if (pun_strlen($username) < 2)
+ $errors[] = $lang_prof_reg['Username too short'];
+ else if (pun_strlen($username) > 25) // This usually doesn't happen since the form element only accepts 25 characters
+ $errors[] = $lang_prof_reg['Username too long'];
+ else if (!strcasecmp($username, 'Guest') || !strcasecmp($username, $lang_common['Guest']))
+ $errors[] = $lang_prof_reg['Username guest'];
+ else if (preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $username) || preg_match('/((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))/', $username))
+ $errors[] = $lang_prof_reg['Username IP'];
+ else if ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false)
+ $errors[] = $lang_prof_reg['Username reserved chars'];
+ else if (preg_match('/(?:\[\/?(?:b|u|s|ins|del|em|i|h|colou?r|quote|code|img|url|email|list|\*)\]|\[(?:img|url|quote|list)=)/i', $username))
+ $errors[] = $lang_prof_reg['Username BBCode'];
+
+ // Check username for any censored words
+ if ($pun_config['o_censoring'] == '1' && censor_words($username) != $username)
+ $errors[] = $lang_register['Username censor'];
+
+ // Check that the username (or a too similar username) is not already registered
+ $query = ($exclude_id) ? ' AND id!='.$exclude_id : '';
+
+ $result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE (UPPER(username)=UPPER(\''.$db->escape($username).'\') OR UPPER(username)=UPPER(\''.$db->escape(preg_replace('/[^\w]/', '', $username)).'\')) AND id>1'.$query) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result))
+ {
+ $busy = $db->result($result);
+ $errors[] = $lang_register['Username dupe 1'].' '.pun_htmlspecialchars($busy).'. '.$lang_register['Username dupe 2'];
+ }
+
+ // Check username for any banned usernames
+ foreach ($pun_bans as $cur_ban)
+ {
+ if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username']))
+ {
+ $errors[] = $lang_prof_reg['Banned username'];
+ break;
+ }
+ }
+}
+
+
+//
+// Update "Users online"
+//
+function update_users_online()
+{
+ global $db, $pun_config;
+
+ $now = time();
+
+ // Fetch all online list entries that are older than "o_timeout_online"
+ $result = $db->query('SELECT user_id, ident, logged, idle FROM '.$db->prefix.'online WHERE logged<'.($now-$pun_config['o_timeout_online'])) or error('Unable to fetch old entries from online list', __FILE__, __LINE__, $db->error());
+ while ($cur_user = $db->fetch_assoc($result))
+ {
+ // If the entry is a guest, delete it
+ if ($cur_user['user_id'] == '1')
+ $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($cur_user['ident']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+ else
+ {
+ // If the entry is older than "o_timeout_visit", update last_visit for the user in question, then delete him/her from the online list
+ if ($cur_user['logged'] < ($now-$pun_config['o_timeout_visit']))
+ {
+ $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$cur_user['logged'].' WHERE id='.$cur_user['user_id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
+ $db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$cur_user['user_id']) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+ }
+ else if ($cur_user['idle'] == '0')
+ $db->query('UPDATE '.$db->prefix.'online SET idle=1 WHERE user_id='.$cur_user['user_id']) or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
+ }
+ }
+}
+
+
+//
+// Generate the "navigator" that appears at the top of every page
+//
+function generate_navlinks()
+{
+ global $pun_config, $lang_common, $pun_user;
+
+ // Index and Userlist should always be displayed
+ $links[] = '
';
+ }
+ }
+
+ // Are there any additional navlinks we should insert into the array before imploding it?
+ if ($pun_config['o_additional_navlinks'] != '')
+ {
+ if (preg_match_all('#([0-9]+)\s*=\s*(.*?)\n#s', $pun_config['o_additional_navlinks']."\n", $extra_links))
+ {
+ // Insert any additional links into the $links array (at the correct index)
+ $num_links = count($extra_links[1]);
+ for ($i = 0; $i < $num_links; ++$i)
+ array_splice($links, $extra_links[1][$i], 0, array('
';
+}
+
+
+//
+// Display the profile navigation menu
+//
+function generate_profile_menu($page = '')
+{
+ global $lang_profile, $pun_config, $pun_user, $id;
+
+?>
+
+
+
+
+
+
+
>
+
>
+
>
+
>
+
>
+
>
+
>
+
+
+
+
+';
+ break;
+ }
+ }
+
+ return $avatar_markup;
+}
+
+
+//
+// Generate browser's title
+//
+function generate_page_title($page_title, $p = null)
+{
+ global $pun_config, $lang_common;
+
+ $page_title = array_reverse($page_title);
+
+ if ($p != null)
+ $page_title[0] .= ' ('.sprintf($lang_common['Page'], forum_number_format($p)).')';
+
+ $crumbs = implode($lang_common['Title separator'], $page_title);
+
+ return $crumbs;
+}
+
+
+//
+// Save array of tracked topics in cookie
+//
+function set_tracked_topics($tracked_topics)
+{
+ global $cookie_name, $cookie_path, $cookie_domain, $cookie_secure, $pun_config;
+
+ $cookie_data = '';
+ if (!empty($tracked_topics))
+ {
+ // Sort the arrays (latest read first)
+ arsort($tracked_topics['topics'], SORT_NUMERIC);
+ arsort($tracked_topics['forums'], SORT_NUMERIC);
+
+ // Homebrew serialization (to avoid having to run unserialize() on cookie data)
+ foreach ($tracked_topics['topics'] as $id => $timestamp)
+ $cookie_data .= 't'.$id.'='.$timestamp.';';
+ foreach ($tracked_topics['forums'] as $id => $timestamp)
+ $cookie_data .= 'f'.$id.'='.$timestamp.';';
+
+ // Enforce a 4048 byte size limit (4096 minus some space for the cookie name)
+ if (strlen($cookie_data) > 4048)
+ {
+ $cookie_data = substr($cookie_data, 0, 4048);
+ $cookie_data = substr($cookie_data, 0, strrpos($cookie_data, ';')).';';
+ }
+ }
+
+ forum_setcookie($cookie_name.'_track', $cookie_data, time() + $pun_config['o_timeout_visit']);
+ $_COOKIE[$cookie_name.'_track'] = $cookie_data; // Set it directly in $_COOKIE as well
+}
+
+
+//
+// Extract array of tracked topics from cookie
+//
+function get_tracked_topics()
+{
+ global $cookie_name;
+
+ $cookie_data = isset($_COOKIE[$cookie_name.'_track']) ? $_COOKIE[$cookie_name.'_track'] : false;
+ if (!$cookie_data)
+ return array('topics' => array(), 'forums' => array());
+
+ if (strlen($cookie_data) > 4048)
+ return array('topics' => array(), 'forums' => array());
+
+ // Unserialize data from cookie
+ $tracked_topics = array('topics' => array(), 'forums' => array());
+ $temp = explode(';', $cookie_data);
+ foreach ($temp as $t)
+ {
+ $type = substr($t, 0, 1) == 'f' ? 'forums' : 'topics';
+ $id = intval(substr($t, 1));
+ $timestamp = intval(substr($t, strpos($t, '=') + 1));
+ if ($id > 0 && $timestamp > 0)
+ $tracked_topics[$type][$id] = $timestamp;
+ }
+
+ return $tracked_topics;
+}
+
+
+//
+// Update posts, topics, last_post, last_post_id and last_poster for a forum
+//
+function update_forum($forum_id)
+{
+ global $db;
+
+ $result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
+ list($num_topics, $num_posts) = $db->fetch_row($result);
+
+ $num_posts = $num_posts + $num_topics; // $num_posts is only the sum of all replies (we have to add the topic posts)
+
+ $result = $db->query('SELECT last_post, last_post_id, last_poster FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id.' AND moved_to IS NULL ORDER BY last_post DESC LIMIT 1') or error('Unable to fetch last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result)) // There are topics in the forum
+ {
+ list($last_post, $last_post_id, $last_poster) = $db->fetch_row($result);
+
+ $db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
+ }
+ else // There are no topics
+ $db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
+}
+
+
+//
+// Deletes any avatars owned by the specified user ID
+//
+function delete_avatar($user_id)
+{
+ global $pun_config;
+
+ $filetypes = array('jpg', 'gif', 'png');
+
+ // Delete user avatar
+ foreach ($filetypes as $cur_type)
+ {
+ if (file_exists(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$user_id.'.'.$cur_type))
+ @unlink(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$user_id.'.'.$cur_type);
+ }
+}
+
+
+//
+// Delete a topic and all of it's posts
+//
+function delete_topic($topic_id)
+{
+ global $db;
+
+ // Delete the topic and any redirect topics
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id='.$topic_id.' OR moved_to='.$topic_id) or error('Unable to delete topic', __FILE__, __LINE__, $db->error());
+
+ // Create a list of the post IDs in this topic
+ $post_ids = '';
+ $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
+ while ($row = $db->fetch_row($result))
+ $post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
+
+ // Make sure we have a list of post IDs
+ if ($post_ids != '')
+ {
+ strip_search_index($post_ids);
+
+ // Delete posts in topic
+ $db->query('DELETE FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
+ }
+
+ // Delete any subscriptions for this topic
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id='.$topic_id) or error('Unable to delete subscriptions', __FILE__, __LINE__, $db->error());
+}
+
+
+//
+// Delete a single post
+//
+function delete_post($post_id, $topic_id)
+{
+ global $db;
+
+ $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id.' ORDER BY id DESC LIMIT 2') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ list($last_id, ,) = $db->fetch_row($result);
+ list($second_last_id, $second_poster, $second_posted) = $db->fetch_row($result);
+
+ // Delete the post
+ $db->query('DELETE FROM '.$db->prefix.'posts WHERE id='.$post_id) or error('Unable to delete post', __FILE__, __LINE__, $db->error());
+
+ strip_search_index($post_id);
+
+ // Count number of replies in the topic
+ $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch post count for topic', __FILE__, __LINE__, $db->error());
+ $num_replies = $db->result($result, 0) - 1;
+
+ // If the message we deleted is the most recent in the topic (at the end of the topic)
+ if ($last_id == $post_id)
+ {
+ // If there is a $second_last_id there is more than 1 reply to the topic
+ if (!empty($second_last_id))
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$second_posted.', last_post_id='.$second_last_id.', last_poster=\''.$db->escape($second_poster).'\', num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+ else
+ // We deleted the only reply, so now last_post/last_post_id/last_poster is posted/id/poster from the topic itself
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post=posted, last_post_id=id, last_poster=poster, num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+ }
+ else
+ // Otherwise we just decrement the reply counter
+ $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+}
+
+
+//
+// Delete every .php file in the forum's cache directory
+//
+function forum_clear_cache()
+{
+ $d = dir(FORUM_CACHE_DIR);
+ while (($entry = $d->read()) !== false)
+ {
+ if (substr($entry, -4) == '.php')
+ @unlink(FORUM_CACHE_DIR.$entry);
+ }
+ $d->close();
+}
+
+
+//
+// Replace censored words in $text
+//
+function censor_words($text)
+{
+ global $db;
+ static $search_for, $replace_with;
+
+ // If not already built in a previous call, build an array of censor words and their replacement text
+ if (!isset($search_for))
+ {
+ $result = $db->query('SELECT search_for, replace_with FROM '.$db->prefix.'censoring') or error('Unable to fetch censor word list', __FILE__, __LINE__, $db->error());
+ $num_words = $db->num_rows($result);
+
+ $search_for = array();
+ for ($i = 0; $i < $num_words; ++$i)
+ {
+ list($search_for[$i], $replace_with[$i]) = $db->fetch_row($result);
+ $search_for[$i] = '/\b('.str_replace('\*', '\w*?', preg_quote($search_for[$i], '/')).')\b/i';
+ }
+ }
+
+ if (!empty($search_for))
+ $text = substr(preg_replace($search_for, $replace_with, ' '.$text.' '), 1, -1);
+
+ return $text;
+}
+
+
+//
+// Determines the correct title for $user
+// $user must contain the elements 'username', 'title', 'posts', 'g_id' and 'g_user_title'
+//
+function get_title($user)
+{
+ global $db, $pun_config, $pun_bans, $lang_common;
+ static $ban_list, $pun_ranks;
+
+ // If not already built in a previous call, build an array of lowercase banned usernames
+ if (empty($ban_list))
+ {
+ $ban_list = array();
+
+ foreach ($pun_bans as $cur_ban)
+ $ban_list[] = strtolower($cur_ban['username']);
+ }
+
+ // If not already loaded in a previous call, load the cached ranks
+ if ($pun_config['o_ranks'] == '1' && empty($pun_ranks))
+ {
+ if (file_exists(FORUM_CACHE_DIR.'cache_ranks.php'))
+ include FORUM_CACHE_DIR.'cache_ranks.php';
+
+ if (!defined('PUN_RANKS_LOADED'))
+ {
+ if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
+ require PUN_ROOT.'include/cache.php';
+
+ generate_ranks_cache();
+ require FORUM_CACHE_DIR.'cache_ranks.php';
+ }
+ }
+
+ // If the user has a custom title
+ if ($user['title'] != '')
+ $user_title = pun_htmlspecialchars($user['title']);
+ // If the user is banned
+ else if (in_array(strtolower($user['username']), $ban_list))
+ $user_title = $lang_common['Banned'];
+ // If the user group has a default user title
+ else if ($user['g_user_title'] != '')
+ $user_title = pun_htmlspecialchars($user['g_user_title']);
+ // If the user is a guest
+ else if ($user['g_id'] == PUN_GUEST)
+ $user_title = $lang_common['Guest'];
+ else
+ {
+ // Are there any ranks?
+ if ($pun_config['o_ranks'] == '1' && !empty($pun_ranks))
+ {
+ foreach ($pun_ranks as $cur_rank)
+ {
+ if (intval($user['num_posts']) >= $cur_rank['min_posts'])
+ $user_title = pun_htmlspecialchars($cur_rank['rank']);
+ }
+ }
+
+ // If the user didn't "reach" any rank (or if ranks are disabled), we assign the default
+ if (!isset($user_title))
+ $user_title = $lang_common['Member'];
+ }
+
+ return $user_title;
+}
+
+
+//
+// Generate a string with numbered links (for multipage scripts)
+//
+function paginate($num_pages, $cur_page, $link)
+{
+ global $lang_common;
+
+ $pages = array();
+ $link_to_all = false;
+
+ // If $cur_page == -1, we link to all pages (used in viewforum.php)
+ if ($cur_page == -1)
+ {
+ $cur_page = 1;
+ $link_to_all = true;
+ }
+
+ if ($num_pages <= 1)
+ $pages = array('1');
+ else
+ {
+ // Add a previous page link
+ if ($num_pages > 1 && $cur_page > 1)
+ $pages[] = ''.$lang_common['Previous'].'';
+
+ if ($cur_page > 3)
+ {
+ $pages[] = '1';
+
+ if ($cur_page > 5)
+ $pages[] = ''.$lang_common['Spacer'].'';
+ }
+
+ // Don't ask me how the following works. It just does, OK? :-)
+ for ($current = ($cur_page == 5) ? $cur_page - 3 : $cur_page - 2, $stop = ($cur_page + 4 == $num_pages) ? $cur_page + 4 : $cur_page + 3; $current < $stop; ++$current)
+ {
+ if ($current < 1 || $current > $num_pages)
+ continue;
+ else if ($current != $cur_page || $link_to_all)
+ $pages[] = ''.forum_number_format($current).'';
+ else
+ $pages[] = ''.forum_number_format($current).'';
+ }
+
+ if ($cur_page <= ($num_pages-3))
+ {
+ if ($cur_page != ($num_pages-3) && $cur_page != ($num_pages-4))
+ $pages[] = ''.$lang_common['Spacer'].'';
+
+ $pages[] = ''.forum_number_format($num_pages).'';
+ }
+
+ // Add a next page link
+ if ($num_pages > 1 && !$link_to_all && $cur_page < $num_pages)
+ $pages[] = ''.$lang_common['Next'].'';
+ }
+
+ return implode(' ', $pages);
+}
+
+
+//
+// Display a message
+//
+function message($message, $no_back_link = false)
+{
+ global $db, $lang_common, $pun_config, $pun_start, $tpl_main;
+
+ if (!defined('PUN_HEADER'))
+ {
+ global $pun_user;
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_common['Info']);
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+ }
+
+?>
+
+
';
+ }
+ }
+ }
+
+ // Add paragraph tag around post, but make sure there are no empty paragraphs
+ $text = preg_replace('# \s*? ((\s* )*)#i', "
$1
", $text);
+ $text = str_replace('
', '
', $text);
+ $text = str_replace('
', '', '
'.$text.'
');
+
+ return $text;
+}
+
+
+//
+// Parse signature text
+//
+function parse_signature($text)
+{
+ global $pun_config, $lang_common, $pun_user;
+
+ if ($pun_config['o_censoring'] == '1')
+ $text = censor_words($text);
+
+ // Convert applicable characters to HTML entities
+ $text = pun_htmlspecialchars($text);
+
+ if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
+ $text = do_bbcode($text, true);
+
+ if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] == '1')
+ $text = do_smilies($text);
+
+
+ // Deal with newlines, tabs and multiple spaces
+ $pattern = array("\n", "\t", ' ', ' ');
+ $replace = array(' ', ' ', ' ', ' ');
+ $text = str_replace($pattern, $replace, $text);
+
+ // Add paragraph tag around post, but make sure there are no empty paragraphs
+ $text = preg_replace('# \s*? ((\s* )*)#i', "$1
", $text);
+ $text = str_replace('
', '
', $text);
+ $text = str_replace('
', '', '
'.$text.'
');
+
+ return $text;
+}
diff --git a/include/search_idx.php b/include/search_idx.php
new file mode 100644
index 0000000..d43f5ea
--- /dev/null
+++ b/include/search_idx.php
@@ -0,0 +1,311 @@
+`"„\|,@_\?~\+\[\]{}:=\/#\\\\;!\.…\s•'.($idx ? '%\*' : '').']+/u', ' ', $text);
+
+ // Replace multiple dashes with just one
+ $text = preg_replace('/-{2,}/', '-', $text);
+
+ // Fill an array with all the words
+ $words = array_unique(explode(' ', $text));
+
+ // Remove any words that should not be indexed
+ foreach ($words as $key => $value)
+ {
+ // If the word shouldn't be indexed, remove it
+ if (!validate_search_word($value, $idx))
+ unset($words[$key]);
+ }
+
+ return $words;
+}
+
+
+//
+// Checks if a word is a valid searchable word
+//
+function validate_search_word($word, $idx)
+{
+ global $pun_user, $pun_config;
+ static $stopwords;
+
+ // If the word is a keyword we don't want to index it, but we do want to be allowed to search it
+ if (is_keyword($word))
+ return !$idx;
+
+ $language = isset($pun_user['language']) ? $pun_user['language'] : $pun_config['o_default_lang'];
+ if (!isset($stopwords))
+ {
+ if (file_exists(PUN_ROOT.'lang/'.$language.'/stopwords.txt'))
+ {
+ $stopwords = file(PUN_ROOT.'lang/'.$language.'/stopwords.txt');
+ $stopwords = array_map('pun_trim', $stopwords);
+ $stopwords = array_filter($stopwords);
+ }
+ else
+ $stopwords = array();
+ }
+
+ // If it is a stopword it isn't valid
+ if (in_array($word, $stopwords))
+ return false;
+
+ // If the word if CJK we don't want to index it, but we do want to be allowed to search it
+ if (is_cjk($word))
+ return !$idx;
+
+ // Check the word is within the min/max length
+ $num_chars = pun_strlen($word);
+ return $num_chars >= PUN_SEARCH_MIN_WORD && $num_chars <= PUN_SEARCH_MAX_WORD;
+}
+
+
+//
+// Check a given word is a search keyword.
+//
+function is_keyword($word)
+{
+ return $word == 'and' || $word == 'or' || $word == 'not';
+}
+
+
+//
+// Check if a given word is CJK or Hangul.
+//
+function is_cjk($word)
+{
+ return preg_match('/^'.PUN_CJK_HANGUL_REGEX.'+$/u', $word) ? true : false;
+}
+
+
+//
+// Strip [img] [url] and [email] out of the message so we don't index their contents
+//
+function strip_bbcode($text)
+{
+ static $patterns;
+
+ if (!isset($patterns))
+ {
+ $patterns = array(
+ '%\[img=([^\]]*+)\][^[]*+\[/img\]%' => '$1', // Keep the alt description
+ '%\[(url|email)=[^\]]*+\]([^[]*+(?:(?!\[/\1\])\[[^[]*+)*)\[/\1\]%' => '$2', // Keep the text
+ '%\[(img|url|email)\]([^[]*+(?:(?!\[/\1\])\[[^[]*+)*)\[/\1\]%' => '', // Remove the whole thing
+ );
+ }
+
+ return preg_replace(array_keys($patterns), array_values($patterns), $text);
+}
+
+
+//
+// Updates the search index with the contents of $post_id (and $subject)
+//
+function update_search_index($mode, $post_id, $message, $subject = null)
+{
+ global $db_type, $db;
+
+ $message = utf8_strtolower($message);
+ $subject = utf8_strtolower($subject);
+
+ // Remove any bbcode that we shouldn't index
+ $message = strip_bbcode($message);
+
+ // Split old and new post/subject to obtain array of 'words'
+ $words_message = split_words($message, true);
+ $words_subject = ($subject) ? split_words($subject, true) : array();
+
+ if ($mode == 'edit')
+ {
+ $result = $db->query('SELECT w.id, w.word, m.subject_match FROM '.$db->prefix.'search_words AS w INNER JOIN '.$db->prefix.'search_matches AS m ON w.id=m.word_id WHERE m.post_id='.$post_id, true) or error('Unable to fetch search index words', __FILE__, __LINE__, $db->error());
+
+ // Declare here to stop array_keys() and array_diff() from complaining if not set
+ $cur_words['post'] = array();
+ $cur_words['subject'] = array();
+
+ while ($row = $db->fetch_row($result))
+ {
+ $match_in = ($row[2]) ? 'subject' : 'post';
+ $cur_words[$match_in][$row[1]] = $row[0];
+ }
+
+ $db->free_result($result);
+
+ $words['add']['post'] = array_diff($words_message, array_keys($cur_words['post']));
+ $words['add']['subject'] = array_diff($words_subject, array_keys($cur_words['subject']));
+ $words['del']['post'] = array_diff(array_keys($cur_words['post']), $words_message);
+ $words['del']['subject'] = array_diff(array_keys($cur_words['subject']), $words_subject);
+ }
+ else
+ {
+ $words['add']['post'] = $words_message;
+ $words['add']['subject'] = $words_subject;
+ $words['del']['post'] = array();
+ $words['del']['subject'] = array();
+ }
+
+ unset($words_message);
+ unset($words_subject);
+
+ // Get unique words from the above arrays
+ $unique_words = array_unique(array_merge($words['add']['post'], $words['add']['subject']));
+
+ if (!empty($unique_words))
+ {
+ $result = $db->query('SELECT id, word FROM '.$db->prefix.'search_words WHERE word IN(\''.implode('\',\'', array_map(array($db, 'escape'), $unique_words)).'\')', true) or error('Unable to fetch search index words', __FILE__, __LINE__, $db->error());
+
+ $word_ids = array();
+ while ($row = $db->fetch_row($result))
+ $word_ids[$row[1]] = $row[0];
+
+ $db->free_result($result);
+
+ $new_words = array_diff($unique_words, array_keys($word_ids));
+ unset($unique_words);
+
+ if (!empty($new_words))
+ {
+ switch ($db_type)
+ {
+ case 'mysql':
+ case 'mysqli':
+ case 'mysql_innodb':
+ case 'mysqli_innodb':
+ $db->query('INSERT INTO '.$db->prefix.'search_words (word) VALUES(\''.implode('\'),(\'', array_map(array($db, 'escape'), $new_words)).'\')');
+ break;
+
+ default:
+ foreach ($new_words as $word)
+ $db->query('INSERT INTO '.$db->prefix.'search_words (word) VALUES(\''.$db->escape($word).'\')');
+ break;
+ }
+ }
+
+ unset($new_words);
+ }
+
+ // Delete matches (only if editing a post)
+ foreach ($words['del'] as $match_in => $wordlist)
+ {
+ $subject_match = ($match_in == 'subject') ? 1 : 0;
+
+ if (!empty($wordlist))
+ {
+ $sql = '';
+ foreach ($wordlist as $word)
+ $sql .= (($sql != '') ? ',' : '').$cur_words[$match_in][$word];
+
+ $db->query('DELETE FROM '.$db->prefix.'search_matches WHERE word_id IN('.$sql.') AND post_id='.$post_id.' AND subject_match='.$subject_match) or error('Unable to delete search index word matches', __FILE__, __LINE__, $db->error());
+ }
+ }
+
+ // Add new matches
+ foreach ($words['add'] as $match_in => $wordlist)
+ {
+ $subject_match = ($match_in == 'subject') ? 1 : 0;
+
+ if (!empty($wordlist))
+ $db->query('INSERT INTO '.$db->prefix.'search_matches (post_id, word_id, subject_match) SELECT '.$post_id.', id, '.$subject_match.' FROM '.$db->prefix.'search_words WHERE word IN(\''.implode('\',\'', array_map(array($db, 'escape'), $wordlist)).'\')') or error('Unable to insert search index word matches', __FILE__, __LINE__, $db->error());
+ }
+
+ unset($words);
+}
+
+
+//
+// Strip search index of indexed words in $post_ids
+//
+function strip_search_index($post_ids)
+{
+ global $db_type, $db;
+
+ switch ($db_type)
+ {
+ case 'mysql':
+ case 'mysqli':
+ case 'mysql_innodb':
+ case 'mysqli_innodb':
+ {
+ $result = $db->query('SELECT word_id FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.') GROUP BY word_id') or error('Unable to fetch search index word match', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result))
+ {
+ $word_ids = '';
+ while ($row = $db->fetch_row($result))
+ $word_ids .= ($word_ids != '') ? ','.$row[0] : $row[0];
+
+ $result = $db->query('SELECT word_id FROM '.$db->prefix.'search_matches WHERE word_id IN('.$word_ids.') GROUP BY word_id HAVING COUNT(word_id)=1') or error('Unable to fetch search index word match', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result))
+ {
+ $word_ids = '';
+ while ($row = $db->fetch_row($result))
+ $word_ids .= ($word_ids != '') ? ','.$row[0] : $row[0];
+
+ $db->query('DELETE FROM '.$db->prefix.'search_words WHERE id IN('.$word_ids.')') or error('Unable to delete search index word', __FILE__, __LINE__, $db->error());
+ }
+ }
+
+ break;
+ }
+
+ default:
+ $db->query('DELETE FROM '.$db->prefix.'search_words WHERE id IN(SELECT word_id FROM '.$db->prefix.'search_matches WHERE word_id IN(SELECT word_id FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.') GROUP BY word_id) GROUP BY word_id HAVING COUNT(word_id)=1)') or error('Unable to delete from search index', __FILE__, __LINE__, $db->error());
+ break;
+ }
+
+ $db->query('DELETE FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.')') or error('Unable to delete search index word match', __FILE__, __LINE__, $db->error());
+}
diff --git a/include/template/admin.tpl b/include/template/admin.tpl
new file mode 100644
index 0000000..06679ee
--- /dev/null
+++ b/include/template/admin.tpl
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+query('SELECT user_id, ident FROM '.$db->prefix.'online WHERE idle=0 ORDER BY ident', true) or error('Unable to fetch online list', __FILE__, __LINE__, $db->error());
+
+ while ($pun_user_online = $db->fetch_assoc($result))
+ {
+ if ($pun_user_online['user_id'] > 1)
+ {
+ if ($pun_user['g_view_users'] == '1')
+ $users[] = "\n\t\t\t\t".'
+here instead.');
+}
+
+// Define PUN because email.php requires it
+define('PUN', 1);
+
+// Make sure we are running at least MIN_PHP_VERSION
+if (!function_exists('version_compare') || version_compare(PHP_VERSION, MIN_PHP_VERSION, '<'))
+ exit('You are running PHP version '.PHP_VERSION.'. FluxBB '.FORUM_VERSION.' requires at least PHP '.MIN_PHP_VERSION.' to run properly. You must upgrade your PHP installation before you can continue.');
+
+// Load the functions script
+require PUN_ROOT.'include/functions.php';
+
+// Load UTF-8 functions
+require PUN_ROOT.'include/utf8/utf8.php';
+
+// Strip out "bad" UTF-8 characters
+forum_remove_bad_characters();
+
+// Reverse the effect of register_globals
+forum_unregister_globals();
+
+// Disable error reporting for uninitialized variables
+error_reporting(E_ALL);
+
+// Force POSIX locale (to prevent functions such as strtolower() from messing up UTF-8 strings)
+setlocale(LC_CTYPE, 'C');
+
+// Turn off magic_quotes_runtime
+if (get_magic_quotes_runtime())
+ set_magic_quotes_runtime(0);
+
+// Strip slashes from GET/POST/COOKIE (if magic_quotes_gpc is enabled)
+if (get_magic_quotes_gpc())
+{
+ function stripslashes_array($array)
+ {
+ return is_array($array) ? array_map('stripslashes_array', $array) : stripslashes($array);
+ }
+
+ $_GET = stripslashes_array($_GET);
+ $_POST = stripslashes_array($_POST);
+ $_COOKIE = stripslashes_array($_COOKIE);
+ $_REQUEST = stripslashes_array($_REQUEST);
+}
+
+// Turn off PHP time limit
+@set_time_limit(0);
+
+//
+// Generate output to be used for config.php
+//
+function generate_config_file()
+{
+ global $db_type, $db_host, $db_name, $db_username, $db_password, $db_prefix, $cookie_name, $cookie_seed;
+
+ return 'Unfortunately no one can be told what FluxBB is - you have to see it for yourself.';
+ $default_lang = 'English';
+ $default_style = 'Air';
+}
+else
+{
+ $db_type = $_POST['req_db_type'];
+ $db_host = pun_trim($_POST['req_db_host']);
+ $db_name = pun_trim($_POST['req_db_name']);
+ $db_username = pun_trim($_POST['db_username']);
+ $db_password = pun_trim($_POST['db_password']);
+ $db_prefix = pun_trim($_POST['db_prefix']);
+ $username = pun_trim($_POST['req_username']);
+ $email = strtolower(pun_trim($_POST['req_email']));
+ $password1 = pun_trim($_POST['req_password1']);
+ $password2 = pun_trim($_POST['req_password2']);
+ $title = pun_trim($_POST['req_title']);
+ $description = pun_trim($_POST['desc']);
+ $base_url = pun_trim($_POST['req_base_url']);
+ $default_lang = pun_trim($_POST['req_default_lang']);
+ $default_style = pun_trim($_POST['req_default_style']);
+ $alerts = array();
+
+ // Make sure base_url doesn't end with a slash
+ if (substr($base_url, -1) == '/')
+ $base_url = substr($base_url, 0, -1);
+
+ // Validate username and passwords
+ if (pun_strlen($username) < 2)
+ $alerts[] = 'Usernames must be at least 2 characters long.';
+ else if (pun_strlen($username) > 25) // This usually doesn't happen since the form element only accepts 25 characters
+ $alerts[] = 'Usernames must not be more than 25 characters long.';
+ else if (!strcasecmp($username, 'Guest'))
+ $alerts[] = 'The username guest is reserved.';
+ else if (preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $username) || preg_match('/((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))/', $username))
+ $alerts[] = 'Usernames may not be in the form of an IP address.';
+ else if ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false)
+ $alerts[] = 'Usernames may not contain all the characters \', " and [ or ] at once.';
+ else if (preg_match('/(?:\[\/?(?:b|u|i|h|colou?r|quote|code|img|url|email|list)\]|\[(?:code|quote|list)=)/i', $username))
+ $alerts[] = 'Usernames may not contain any of the text formatting tags (BBCode) that the forum uses.';
+
+ if (pun_strlen($password1) < 4)
+ $alerts[] = 'Passwords must be at least 4 characters long.';
+ else if ($password1 != $password2)
+ $alerts[] = 'Passwords do not match.';
+
+ // Validate email
+ require PUN_ROOT.'include/email.php';
+
+ if (!is_valid_email($email))
+ $alerts[] = 'The administrator email address you entered is invalid.';
+
+ if ($title == '')
+ $alerts[] = 'You must enter a board title.';
+
+ $default_lang = preg_replace('#[\.\\\/]#', '', $default_lang);
+ if (!file_exists(PUN_ROOT.'lang/'.$default_lang.'/common.php'))
+ $alerts[] = 'The default language chosen doesn\'t seem to exist.';
+
+ $default_style = preg_replace('#[\.\\\/]#', '', $default_style);
+ if (!file_exists(PUN_ROOT.'style/'.$default_style.'.css'))
+ $alerts[] = 'The default style chosen doesn\'t seem to exist.';
+}
+
+if (!isset($_POST['form_sent']) || !empty($alerts))
+{
+ // Determine available database extensions
+ $dual_mysql = false;
+ $db_extensions = array();
+ $mysql_innodb = false;
+ if (function_exists('mysqli_connect'))
+ {
+ $db_extensions[] = array('mysqli', 'MySQL Improved');
+ $db_extensions[] = array('mysqli_innodb', 'MySQL Improved (InnoDB)');
+ $mysql_innodb = true;
+ }
+ if (function_exists('mysql_connect'))
+ {
+ $db_extensions[] = array('mysql', 'MySQL Standard');
+ $db_extensions[] = array('mysql_innodb', 'MySQL Standard (InnoDB)');
+ $mysql_innodb = true;
+
+ if (count($db_extensions) > 2)
+ $dual_mysql = true;
+ }
+ if (function_exists('sqlite_open'))
+ $db_extensions[] = array('sqlite', 'SQLite');
+ if (function_exists('pg_connect'))
+ $db_extensions[] = array('pgsql', 'PostgreSQL');
+
+ if (empty($db_extensions))
+ exit('This PHP environment does not have support for any of the databases that FluxBB supports. PHP needs to have support for either MySQL, PostgreSQL or SQLite in order for FluxBB to be installed.');
+
+?>
+
+
+
+
+
+FluxBB Installation
+
+
+
+
+
+
+
+
+
+
+
+
+
FluxBB Installation
+
Welcome to FluxBB installation. You are about to install FluxBB. In order to install FluxBB, you must complete the form set out below. If you encounter any difficulties with the installation, please refer to the documentation.
+
+
+
+ 'No user by that username registered. If you want to add a ban not tied to a specific username just leave the username blank.',
+'No user ID message' => 'No user by that ID registered.',
+'User is admin message' => 'The user %s is an administrator and can\'t be banned. If you want to ban an administrator, you must first demote him/her to moderator or user.',
+'Must enter message' => 'You must enter either a username, an IP address or an email address (at least).',
+'Cannot ban guest message' => 'The guest user cannot be banned.',
+'Invalid IP message' => 'You entered an invalid IP/IP-range.',
+'Invalid e-mail message' => 'The email address (e.g. user@domain.com) or partial email address domain (e.g. domain.com) you entered is invalid.',
+'Invalid date message' => 'You entered an invalid expire date.',
+'Invalid date reasons' => 'The format should be YYYY-MM-DD and the date must be at least one day in the future.',
+'Ban added redirect' => 'Ban added. Redirecting …' ,
+'Ban edited redirect' => 'Ban edited. Redirecting …',
+'Ban removed redirect' => 'Ban removed. Redirecting …',
+
+'New ban head' => 'New ban',
+'Add ban subhead' => 'Add ban',
+'Username label' => 'Username',
+'Username help' => 'The username to ban (case-insensitive).',
+'Username advanced help' => 'The username to ban (case-insensitive). The next page will let you enter a custom IP and email. If you just want to ban a specific IP/IP-range or email just leave it blank.',
+
+'Ban search head' => 'Ban search',
+'Ban search subhead' => 'Enter search criteria',
+'Ban search info' => 'Search for bans in the database. You can enter one or more terms to search for. Wildcards in the form of asterisks (*) are accepted.',
+'Date help' => '(yyyy-mm-dd)',
+'Message label' => 'Message',
+'Expire after label' => 'Expire after',
+'Expire before label' => 'Expire before',
+'Order by label' => 'Order by',
+'Order by username' => 'Username',
+'Order by ip' => 'IP',
+'Order by e-mail' => 'Email',
+'Order by expire' => 'Expire date',
+'Ascending' => 'Ascending',
+'Descending' => 'Descending',
+'Submit search' => 'Submit search',
+
+'E-mail label' => 'Email',
+'E-mail help' => 'The email or email domain you wish to ban (e.g. someone@somewhere.com or somewhere.com). See "Allow banned email addresses" in Permissions for more info.',
+'IP label' => 'IP address/IP-ranges',
+'IP help' => 'The IP address or IP-ranges you wish to ban (e.g. 150.11.110.1 or 150.11.110). Separate addresses with spaces. If an IP is entered already it is the last known IP of this user in the database.',
+'IP help link' => 'Click %s to see IP statistics for this user.',
+'Ban advanced head' => 'Ban advanced settings',
+'Ban advanced subhead' => 'Supplement ban with IP and email',
+'Ban message label' => 'Ban message',
+'Ban message help' => 'A message that will be displayed to the banned user when he/she visits the board.',
+'Message expiry subhead' => 'Ban message and expiry',
+'Ban IP range info' => 'You should be very careful when banning an IP-range because of the possibility of multiple users matching the same partial IP.',
+'Expire date label' => 'Expire date',
+'Expire date help' => 'The date when this ban should be automatically removed (format: yyyy-mm-dd). Leave blank to remove manually.',
+
+'Results head' => 'Search Results',
+'Results username head' => 'Username',
+'Results e-mail head' => 'Email',
+'Results IP address head' => 'IP/IP-ranges',
+'Results expire head' => 'Expires',
+'Results message head' => 'Message',
+'Results banned by head' => 'Banned by',
+'Results actions head' => 'Actions',
+'No match' => 'No match',
+'Unknown' => 'Unknown',
+
+);
diff --git a/lang/English/admin_categories.php b/lang/English/admin_categories.php
new file mode 100644
index 0000000..311a5af
--- /dev/null
+++ b/lang/English/admin_categories.php
@@ -0,0 +1,29 @@
+ 'You must enter a name for the category',
+'Category added redirect' => 'Category added. Redirecting …',
+'Category deleted redirect' => 'Category deleted. Redirecting …',
+'Delete category head' => 'Delete category (together with all forums and posts it contains)',
+'Confirm delete subhead' => 'Confirm delete category',
+'Confirm delete info' => 'Are you sure that you want to delete the category %s?',
+'Delete category warn' => 'WARNING! Deleting a category will delete all forums and posts (if any) in this category!',
+'Must enter integer message' => 'Position must be a positive integer value.',
+'Categories updated redirect' => 'Categories updated. Redirecting …',
+'Add categories head' => 'Add categories',
+'Add categories subhead' => 'Add categories',
+'Add category label' => 'Add a new category',
+'Add new submit' => 'Add new',
+'Add category help' => 'The name of the new category you want to add. You can edit the name of the category later (see below). Go to %s to add forums to your new category.',
+'Delete categories head' => 'Delete categories',
+'Delete categories subhead' => 'Delete categories',
+'Delete category label' => 'Delete a category',
+'Delete category help' => 'Select the name of the category you want to delete. You will be asked to confirm your choice of category for deletion before it is deleted.',
+'Edit categories head' => 'Edit categories',
+'Edit categories subhead' => 'Edit categories',
+'Category position label' => 'Position',
+'Category name label' => 'Name',
+
+);
diff --git a/lang/English/admin_censoring.php b/lang/English/admin_censoring.php
new file mode 100644
index 0000000..f112ba1
--- /dev/null
+++ b/lang/English/admin_censoring.php
@@ -0,0 +1,20 @@
+ 'You must enter both a word to censor and text to replace it with.',
+'Must search both message' => 'You must enter both text to search for and text to replace with.',
+'Word updated redirect' => 'Censor word updated. Redirecting …',
+'Word added redirect' => 'Censor word added. Redirecting …',
+'Word removed redirect' => 'Censor word removed. Redirecting …',
+'Censoring head' => 'Censoring',
+'Add word subhead' => 'Add word',
+'Add word info' => 'Enter a word that you want to censor and the replacement text for this word. Wildcards are accepted (i.e. *some* would match somewhere and lonesome). Censor words also affect usernames. New users will not be able to register with usernames containing any censored words. The search is case insensitive. Censor words must be enabled in %s for this to have any effect.',
+'Censored word label' => 'Censored word',
+'Replacement label' => 'Replacement word(s)',
+'Action label' => 'Action',
+'Edit remove subhead' => 'Edit or remove words',
+'No words in list' => 'No censor words in list.',
+
+);
diff --git a/lang/English/admin_common.php b/lang/English/admin_common.php
new file mode 100644
index 0000000..a87616c
--- /dev/null
+++ b/lang/English/admin_common.php
@@ -0,0 +1,44 @@
+ 'Admin menu',
+'Plugins menu' => 'Plugins menu',
+'Moderator menu' => 'Moderator menu',
+'Index' => 'Index',
+'Categories' => 'Categories',
+'Forums' => 'Forums',
+'Users' => 'Users',
+'User groups' => 'User groups',
+'Options' => 'Options',
+'Permissions' => 'Permissions',
+'Censoring' => 'Censoring',
+'Ranks' => 'Ranks',
+'Bans' => 'Bans',
+'Prune' => 'Prune',
+'Maintenance' => 'Maintenance',
+'Reports' => 'Reports',
+
+'Admin' => 'Admin',
+'Go back' => 'Go back',
+'Delete' => 'Delete',
+'Update' => 'Update',
+'Add' => 'Add',
+'Edit' => 'Edit',
+'Remove' => 'Remove',
+'Yes' => 'Yes',
+'No' => 'No',
+'Save changes' => 'Save changes',
+'Save' => 'Save',
+'here' => 'here',
+'Action' => 'Action',
+'None' => 'None',
+'Maintenance mode' => 'maintenance mode', // Used for link text in more than one file
+
+// Admin loader
+'No plugin message' => 'There is no plugin called %s in the plugin directory.',
+'Plugin failed message' => 'Loading of the plugin - %s - failed.',
+
+);
diff --git a/lang/English/admin_forums.php b/lang/English/admin_forums.php
new file mode 100644
index 0000000..f13876d
--- /dev/null
+++ b/lang/English/admin_forums.php
@@ -0,0 +1,51 @@
+ 'Forum added. Redirecting …',
+'Forum deleted redirect' => 'Forum deleted. Redirecting …',
+'Forums updated redirect' => 'Forums updated. Redirecting …',
+'Forum updated redirect' => 'Forum updated. Redirecting …',
+'Perms reverted redirect' => 'Permissions reverted to defaults. Redirecting …',
+'Must enter name message' => 'You must enter a forum name.',
+'Must be integer message' => 'Position must be a positive integer value.',
+
+// Entry page
+'Add forum head' => 'Add forum',
+'Create new subhead' => 'Create a new forum',
+'Add forum label' => 'Add forum to category',
+'Add forum help' => 'Select the category to which you wish to add a new forum.',
+'Add forum' => 'Add forum',
+'No categories exist' => 'No categories exist',
+'Edit forums head' => 'Edit forums',
+'Category subhead' => 'Category:',
+'Forum label' => 'Forum',
+'Edit link' => 'Edit',
+'Delete link' => 'Delete',
+'Position label' => 'Position',
+'Update positions' => 'Update positions',
+'Confirm delete head' => 'Confirm delete forum',
+'Confirm delete subhead' => 'Important! Read before deleting',
+'Confirm delete info' => 'Are you sure that you want to delete the forum %s?',
+'Confirm delete warn' => 'WARNING! Deleting a forum will delete all posts (if any) in that forum!',
+
+// Detailed edit page
+'Edit forum head' => 'Edit forum',
+'Edit details subhead' => 'Edit forum details',
+'Forum name label' => 'Forum name',
+'Forum description label' => 'Description (HTML)',
+'Category label' => 'Category',
+'Sort by label' => 'Sort topics by',
+'Last post' => 'Last post',
+'Topic start' => 'Topic start',
+'Redirect label' => 'Redirect URL',
+'Redirect help' => 'Only available in empty forums',
+'Group permissions subhead' => 'Edit group permissions for this forum',
+'Group permissions info' => 'In this form, you can set the forum specific permissions for the different user groups. If you haven\'t made any changes to this forum\'s group permissions, what you see below is the default based on settings in %s. Administrators always have full permissions and are thus excluded. Permission settings that differ from the default permissions for the user group are marked red. The "Read forum" permission checkbox will be disabled if the group in question lacks the "Read board" permission. For redirect forums, only the "Read forum" permission is editable.',
+'Read forum label' => 'Read forum',
+'Post replies label' => 'Post replies',
+'Post topics label' => 'Post topics',
+'Revert to default' => 'Revert to default',
+
+);
diff --git a/lang/English/admin_groups.php b/lang/English/admin_groups.php
new file mode 100644
index 0000000..dd6ad56
--- /dev/null
+++ b/lang/English/admin_groups.php
@@ -0,0 +1,82 @@
+ 'You must enter a group title.',
+'Title already exists message' => 'There is already a group with the title %s.',
+'Default group redirect' => 'Default group set. Redirecting …',
+'Cannot remove default message' => 'The default group cannot be removed. In order to delete this group, you must first setup a different group as the default.',
+'Group removed redirect' => 'Group removed. Redirecting …',
+'Group added redirect' => 'Group added. Redirecting …',
+'Group edited redirect' => 'Group edited. Redirecting …',
+
+'Add groups head' => 'Add/setup groups',
+'Add group subhead' => 'Add new group',
+'New group label' => 'Base new group on',
+'New group help' => 'Select a user group from which the new group will inherit its permission settings. The next page will let you fine-tune its settings.',
+'Default group subhead' => 'Set default group',
+'Default group label' => 'Default group',
+'Default group help' => 'This is the default user group, e.g. the group users are placed in when they register. For security reasons, users can\'t be placed in either the moderator or administrator user groups by default.',
+'Existing groups head' => 'Existing groups',
+'Edit groups subhead' => 'Edit/delete groups',
+'Edit groups info' => 'The pre-defined groups Guests, Administrators, Moderators and Members cannot be removed. However, they can be edited. Please note that in some groups, some options are unavailable (e.g. the edit posts permission for guests). Administrators always have full permissions.',
+'Edit link' => 'Edit',
+'Delete link' => 'Delete',
+'Group delete head' => 'Group delete',
+'Confirm delete subhead' => 'Confirm delete group',
+'Confirm delete info' => 'Are you sure that you want to delete the group %s?',
+'Confirm delete warn' => 'WARNING! After you deleted a group you can not restore it.',
+'Delete group head' => 'Delete group',
+'Move users subhead' => 'Move users currently in group',
+'Move users info' => 'The group %s currently has %s members. Please select a group to which these members will be assigned upon deletion.',
+'Move users label' => 'Move users to',
+'Delete group' => 'Delete group',
+
+'Group settings head' => 'Group settings',
+'Group settings subhead' => 'Setup group options and permissions',
+'Group settings info' => 'Below options and permissions are the default permissions for the user group. These options apply if no forum specific permissions are in effect.',
+'Group title label' => 'Group title',
+'User title label' => 'User title',
+'User title help' => 'This title will override any rank users in this group have attained. Leave blank to use default title or rank.',
+'Mod privileges label' => 'Allow users moderator privileges',
+'Mod privileges help' => 'In order for a user in this group to have moderator abilities, he/she must be assigned to moderate one or more forums. This is done via the user administration page of the user\'s profile.',
+'Edit profile label' => 'Allow moderators to edit user profiles',
+'Edit profile help' => 'If moderator privileges are enabled, allow users in this group to edit user profiles.',
+'Rename users label' => 'Allow moderators to rename users',
+'Rename users help' => 'If moderator privileges are enabled, allow users in this group to rename users.',
+'Change passwords label' => 'Allow moderators to change passwords',
+'Change passwords help' => 'If moderator privileges are enabled, allow users in this group to change user passwords.',
+'Ban users label' => 'Allow moderators to ban users',
+'Ban users help' => 'If moderator privileges are enabled, allow users in this group to ban users.',
+'Read board label' => 'Read board',
+'Read board help' => 'Allow users in this group to view the board. This setting applies to every aspect of the board and can therefore not be overridden by forum specific settings. If this is set to "No", users in this group will only be able to login/logout and register.',
+'View user info label' => 'View user information',
+'View user info help' => 'Allow users to view the user list and user profiles.',
+'Post replies label' => 'Post replies',
+'Post replies help' => 'Allow users in this group to post replies in topics.',
+'Post topics label' => 'Post topics',
+'Post topics help' => 'Allow users in this group to post new topics.',
+'Edit posts label' => 'Edit posts',
+'Edit posts help' => 'Allow users in this group to edit their own posts.',
+'Delete posts label' => 'Delete posts',
+'Delete posts help' => 'Allow users in this group to delete their own posts.',
+'Delete topics label' => 'Delete topics',
+'Delete topics help' => 'Allow users in this group to delete their own topics (including any replies).',
+'Set own title label' => 'Set own user title',
+'Set own title help' => 'Allow users in this group to set their own user title.',
+'User search label' => 'Use search',
+'User search help' => 'Allow users in this group to use the search feature.',
+'User list search label' => 'Search user list',
+'User list search help' => 'Allow users in this group to freetext search for users in the user list.',
+'Send e-mails label' => 'Send e-mails',
+'Send e-mails help' => 'Allow users in this group to send e-mails to other users.',
+'Post flood label' => 'Post flood interval',
+'Post flood help' => 'Number of seconds that users in this group have to wait between posts. Set to 0 to disable.',
+'Search flood label' => 'Search flood interval',
+'Search flood help' => 'Number of seconds that users in this group have to wait between searches. Set to 0 to disable.',
+'E-mail flood label' => 'Email flood interval',
+'E-mail flood help' => 'Number of seconds that users in this group have to wait between emails. Set to 0 to disable.',
+'Moderator info' => 'Please note that in order for a user in this group to have moderator abilities, he/she must be assigned to moderate one or more forums. This is done via the user administration page of the user\'s profile.',
+
+);
diff --git a/lang/English/admin_index.php b/lang/English/admin_index.php
new file mode 100644
index 0000000..9f9cdc7
--- /dev/null
+++ b/lang/English/admin_index.php
@@ -0,0 +1,51 @@
+ 'Unable to check for upgrade since \'allow_url_fopen\' is disabled on this system.',
+'Upgrade check failed message' => 'Check for upgrade failed for unknown reasons.',
+'Running latest version message' => 'You are running the latest version of FluxBB.',
+'New version available message' => 'A new version of FluxBB has been released. You can download the latest version at %s.',
+'PHPinfo disabled message' => 'The PHP function phpinfo() has been disabled on this server.',
+'Not available' => 'Not available',
+'Forum admin head' => 'Forum administration',
+'NA' => 'N/A',
+'Welcome to admin' => 'Welcome to the FluxBB administration control panel. From here you can control vital aspects of the board. Depending on whether you are an administrator or a moderator you can:',
+'Welcome 1' => 'Organize categories and forums.',
+'Welcome 2' => 'Set forum-wide options and preferences.',
+'Welcome 3' => 'Control permissions for users and guests.',
+'Welcome 4' => 'View IP statistics for users.',
+'Welcome 5' => 'Ban users.',
+'Welcome 6' => 'Censor words.',
+'Welcome 7' => 'Set up user ranks.',
+'Welcome 8' => 'Prune old posts.',
+'Welcome 9' => 'Handle post reports.',
+'Statistics head' => 'Statistics',
+'FluxBB version label' => 'FluxBB version',
+'Check for upgrade' => 'Check for upgrade',
+'FluxBB version data' => 'v%s - %s',
+'Server load label' => 'Server load',
+'Server load data' => '%s - %s user(s) online',
+'Environment label' => 'Environment',
+'Environment data OS' => 'Operating system: %s',
+'Show info' => 'Show info',
+'Environment data version' => 'PHP: %s - %s',
+'Environment data acc' => 'Accelerator: %s',
+'Turck MMCache' => 'Turk MMCache',
+'Turck MMCache link' => 'turck-mmcache.sourceforge.net',
+'ionCube PHP Accelerator' => 'ionCube PHP Accelerator',
+'ionCube PHP Accelerator link' => 'www.php-accelerator.co.uk/',
+'Alternative PHP Cache (APC)' => 'Alternative PHP Cache (APC)',
+'Alternative PHP Cache (APC) link' => 'www.php.net/apc/',
+'Zend Optimizer' => 'Zend Optimizer',
+'Zend Optimizer link' => 'www.zend.com/products/guard/zend-optimizer',
+'eAccelerator' => 'eAccelerator',
+'eAccelerator link' => 'www.eaccelerator.net/',
+'XCache' => 'XCache',
+'XCache link' => 'xcache.lighttpd.net/',
+'Database label' => 'Database',
+'Database data rows' => 'Rows: %s',
+'Database data size' => 'Size: %s',
+
+);
diff --git a/lang/English/admin_maintenance.php b/lang/English/admin_maintenance.php
new file mode 100644
index 0000000..a0e62b3
--- /dev/null
+++ b/lang/English/admin_maintenance.php
@@ -0,0 +1,23 @@
+ 'Forum maintenance',
+'Rebuild index subhead' => 'Rebuild search index',
+'Rebuild index info' => 'If you\'ve added, edited or removed posts manually in the database or if you\'re having problems searching, you should rebuild the search index. For best performance, you should put the forum in %s during rebuilding. Rebuilding the search index can take a long time and will increase server load during the rebuild process!',
+'Posts per cycle label' => 'Posts per cycle',
+'Posts per cycle help' => 'The number of posts to process per pageview. E.g. if you were to enter 300, three hundred posts would be processed and then the page would refresh. This is to prevent the script from timing out during the rebuild process.',
+'Starting post label' => 'Starting post ID',
+'Starting post help' => 'The post ID to start rebuilding at. The default value is the first available ID in the database. Normally you wouldn\'t want to change this.',
+'Empty index label' => 'Empty index',
+'Empty index help' => 'Select this if you want the search index to be emptied before rebuilding (see below).',
+'Rebuild completed info' => 'Once the process has completed, you will be redirected back to this page. It is highly recommended that you have JavaScript enabled in your browser during rebuilding (for automatic redirect when a cycle has completed). If you are forced to abort the rebuild process, make a note of the last processed post ID and enter that ID+1 in "Starting post ID" when/if you want to continue ("Empty index" must not be selected).',
+'Rebuild index' => 'Rebuild index',
+'Rebuilding search index' => 'Rebuilding search index',
+'Rebuilding index info' => 'Rebuilding index. This might be a good time to put on some coffee :-)',
+'Processing post' => 'Processing post %s …',
+'Click here' => 'Click here',
+'Javascript redirect failed' => 'JavaScript redirect unsuccessful. %s to continue …',
+
+);
diff --git a/lang/English/admin_options.php b/lang/English/admin_options.php
new file mode 100644
index 0000000..e701917
--- /dev/null
+++ b/lang/English/admin_options.php
@@ -0,0 +1,217 @@
+ 'Bad HTTP_REFERER. If you have moved these forums from one location to another or switched domains, you need to update the Base URL manually in the database (look for o_base_url in the config table) and then clear the cache by deleting all .php files in the /cache directory.',
+'Must enter title message' => 'You must enter a board title.',
+'Invalid e-mail message' => 'The admin email address you entered is invalid.',
+'Invalid webmaster e-mail message' => 'The webmaster email address you entered is invalid.',
+'Enter announcement here' => 'Enter your announcement here.',
+'Enter rules here' => 'Enter your rules here.',
+'Default maintenance message' => 'The forums are temporarily down for maintenance. Please try again in a few minutes.',
+'Timeout error message' => 'The value of "Timeout online" must be smaller than the value of "Timeout visit".',
+'Options updated redirect' => 'Options updated. Redirecting …',
+'Options head' => 'Options',
+
+// Essentials section
+'Essentials subhead' => 'Essentials',
+'Board title label' => 'Board title',
+'Board title help' => 'The title of this bulletin board (shown at the top of every page). This field may not contain HTML.',
+'Board desc label' => 'Board description',
+'Board desc help' => 'A short description of this bulletin board (shown at the top of every page). This field may contain HTML.',
+'Base URL label' => 'Base URL',
+'Base URL help' => 'The complete URL of the board without trailing slash (i.e. http://www.mydomain.com/forums). This must be correct in order for all admin and moderator features to work. If you get "Bad referer" errors, it\'s probably incorrect.',
+'Timezone label' => 'Default time zone',
+'Timezone help' => 'The default time zone for guests and users attempting to register for the board.',
+'DST label' => 'Adjust for DST',
+'DST help' => 'Check if daylight savings is in effect (advances times by 1 hour).',
+'Language label' => 'Default language',
+'Language help' => 'The default language for guests and users who haven\'t changed from the default in their profile. If you remove a language pack, this must be updated.',
+'Default style label' => 'Default style',
+'Default style help' => 'The default style for guests and users who haven\'t changed from the default in their profile.',
+
+// Essentials section timezone options
+'UTC-12:00' => '(UTC-12:00) International Date Line West',
+'UTC-11:00' => '(UTC-11:00) Niue, Samoa',
+'UTC-10:00' => '(UTC-10:00) Hawaii-Aleutian, Cook Island',
+'UTC-09:30' => '(UTC-09:30) Marquesas Islands',
+'UTC-09:00' => '(UTC-09:00) Alaska, Gambier Island',
+'UTC-08:30' => '(UTC-08:30) Pitcairn Islands',
+'UTC-08:00' => '(UTC-08:00) Pacific',
+'UTC-07:00' => '(UTC-07:00) Mountain',
+'UTC-06:00' => '(UTC-06:00) Central',
+'UTC-05:00' => '(UTC-05:00) Eastern',
+'UTC-04:00' => '(UTC-04:00) Atlantic',
+'UTC-03:30' => '(UTC-03:30) Newfoundland',
+'UTC-03:00' => '(UTC-03:00) Amazon, Central Greenland',
+'UTC-02:00' => '(UTC-02:00) Mid-Atlantic',
+'UTC-01:00' => '(UTC-01:00) Azores, Cape Verde, Eastern Greenland',
+'UTC' => '(UTC) Western European, Greenwich',
+'UTC+01:00' => '(UTC+01:00) Central European, West African',
+'UTC+02:00' => '(UTC+02:00) Eastern European, Central African',
+'UTC+03:00' => '(UTC+03:00) Moscow, Eastern African',
+'UTC+03:30' => '(UTC+03:30) Iran',
+'UTC+04:00' => '(UTC+04:00) Gulf, Samara',
+'UTC+04:30' => '(UTC+04:30) Afghanistan',
+'UTC+05:00' => '(UTC+05:00) Pakistan, Yekaterinburg',
+'UTC+05:30' => '(UTC+05:30) India, Sri Lanka',
+'UTC+05:45' => '(UTC+05:45) Nepal',
+'UTC+06:00' => '(UTC+06:00) Bangladesh, Bhutan, Novosibirsk',
+'UTC+06:30' => '(UTC+06:30) Cocos Islands, Myanmar',
+'UTC+07:00' => '(UTC+07:00) Indochina, Krasnoyarsk',
+'UTC+08:00' => '(UTC+08:00) Greater China, Australian Western, Irkutsk',
+'UTC+08:45' => '(UTC+08:45) Southeastern Western Australia',
+'UTC+09:00' => '(UTC+09:00) Japan, Korea, Chita',
+'UTC+09:30' => '(UTC+09:30) Australian Central',
+'UTC+10:00' => '(UTC+10:00) Australian Eastern, Vladivostok',
+'UTC+10:30' => '(UTC+10:30) Lord Howe',
+'UTC+11:00' => '(UTC+11:00) Solomon Island, Magadan',
+'UTC+11:30' => '(UTC+11:30) Norfolk Island',
+'UTC+12:00' => '(UTC+12:00) New Zealand, Fiji, Kamchatka',
+'UTC+12:45' => '(UTC+12:45) Chatham Islands',
+'UTC+13:00' => '(UTC+13:00) Tonga, Phoenix Islands',
+'UTC+14:00' => '(UTC+14:00) Line Islands',
+
+// Timeout Section
+'Timeouts subhead' => 'Time and timeouts',
+'Time format label' => 'Time format',
+'PHP manual' => 'PHP manual',
+'Time format help' => '[Current format: %s]. See %s for formatting options.',
+'Date format label' => 'Date format',
+'Date format help' => '[Current format: %s]. See %s for formatting options.',
+'Visit timeout label' => 'Visit timeout',
+'Visit timeout help' => 'Number of seconds a user must be idle before his/hers last visit data is updated (primarily affects new message indicators).',
+'Online timeout label' => 'Online timeout',
+'Online timeout help' => 'Number of seconds a user must be idle before being removed from the online users list.',
+'Redirect time label' => 'Redirect time',
+'Redirect time help' => 'Number of seconds to wait when redirecting. If set to 0, no redirect page will be displayed (not recommended).',
+
+// Display Section
+'Display subhead' => 'Display',
+'Version number label' => 'Version number',
+'Version number help' => 'Show FluxBB version number in footer.',
+'Info in posts label' => 'User info in posts',
+'Info in posts help' => 'Show information about the poster under the username in topic view. The information affected is location, register date, post count and the contact links (email and URL).',
+'Post count label' => 'User post count',
+'Post count help' => 'Show the number of posts a user has made (affects topic view, profile and user list).',
+'Smilies label' => 'Smilies in posts',
+'Smilies help' => 'Convert smilies to small graphic icons.',
+'Smilies sigs label' => 'Smilies in signatures',
+'Smilies sigs help' => 'Convert smilies to small graphic icons in user signatures.',
+'Clickable links label' => 'Make clickable links',
+'Clickable links help' => 'When enabled, FluxBB will automatically detect any URLs in posts and make them clickable hyperlinks.',
+'Topic review label' => 'Topic review',
+'Topic review help' => 'Maximum number of posts to display when posting (newest first). Set to 0 to disable.',
+'Topics per page label' => 'Topics per page',
+'Topics per page help' => 'The default number of topics to display per page in a forum. Users can personalize this setting.',
+'Posts per page label' => 'Posts per page',
+'Posts per page help' => 'The default number of posts to display per page in a topic. Users can personalize this setting.',
+'Indent label' => 'Indent size',
+'Indent help' => 'If set to 8, a regular tab will be used when displaying text within the [code][/code] tag. Otherwise this many spaces will be used to indent the text.',
+'Quote depth label' => 'Maximum [quote] depth',
+'Quote depth help' => 'The maximum times a [quote] tag can go inside other [quote] tags, any tags deeper than this will be discarded.',
+
+// Features section
+'Features subhead' => 'Features',
+'Quick post label' => 'Quick post',
+'Quick post help' => 'When enabled, FluxBB will add a quick post form at the bottom of topics. This way users can post directly from the topic view.',
+'Users online label' => 'Users online',
+'Users online help' => 'Display info on the index page about guests and registered users currently browsing the board.',
+'Censor words label' => 'Censor words',
+'Censor words help' => 'Enable this to censor specific words in the board. See %s for more info.',
+'Signatures label' => 'Signatures',
+'Signatures help' => 'Allow users to attach a signature to their posts.',
+'User ranks label' => 'User ranks',
+'User ranks help' => 'Enable this to use user ranks. See %s for more info.',
+'User has posted label' => 'User has posted earlier',
+'User has posted help' => 'This feature displays a dot in front of topics in viewforum.php in case the currently logged in user has posted in that topic earlier. Disable if you are experiencing high server load.',
+'Topic views label' => 'Topic views',
+'Topic views help' => 'Keep track of the number of views a topic has. Disable if you are experiencing high server load in a busy forum.',
+'Quick jump label' => 'Quick jump',
+'Quick jump help' => 'Enable the quick jump (jump to forum) drop list.',
+'GZip label' => 'GZip output',
+'GZip help' => 'If enabled, FluxBB will gzip the output sent to browsers. This will reduce bandwidth usage, but use a little more CPU. This feature requires that PHP is configured with zlib (--with-zlib). Note: If you already have one of the Apache modules mod_gzip or mod_deflate set up to compress PHP scripts, you should disable this feature.',
+'Search all label' => 'Search all forums',
+'Search all help' => 'When disabled, searches will only be allowed in one forum at a time. Disable if server load is high due to excessive searching.',
+'Menu items label' => 'Additional menu items',
+'Menu items help' => 'By entering HTML hyperlinks into this textbox, any number of items can be added to the navigation menu at the top of all pages. The format for adding new links is X = <a href="URL">LINK</a> where X is the position at which the link should be inserted (e.g. 0 to insert at the beginning and 2 to insert after "User list"). Separate entries with a linebreak.',
+'Default feed label' => 'Default feed type',
+'Default feed help' => 'Select the type of syndication feed to display. Note: Choosing none will not disable feeds, only hide them by default.',
+'None' => 'None',
+'RSS' => 'RSS',
+'Atom' => 'Atom',
+
+// Reports section
+'Reports subhead' => 'Reports',
+'Reporting method label' => 'Reporting method',
+'Internal' => 'Internal',
+'By e-mail' => 'Email',
+'Both' => 'Both',
+'Reporting method help' => 'Select the method for handling topic/post reports. You can choose whether topic/post reports should be handled by the internal report system, emailed to the addresses on the mailing list (see below) or both.',
+'Mailing list label' => 'Mailing list',
+'Mailing list help' => 'A comma separated list of subscribers. The people on this list are the recipients of reports.',
+
+// Avatars section
+'Avatars subhead' => 'Avatars',
+'Use avatars label' => 'Use avatars',
+'Use avatars help' => 'When enabled, users will be able to upload an avatar which will be displayed under their title/rank.',
+'Upload directory label' => 'Upload directory',
+'Upload directory help' => 'The upload directory for avatars (relative to the FluxBB root directory). PHP must have write permissions to this directory.',
+'Max width label' => 'Max width',
+'Max width help' => 'The maximum allowed width of avatars in pixels (60 is recommended).',
+'Max height label' => 'Max height',
+'Max height help' => 'The maximum allowed height of avatars in pixels (60 is recommended).',
+'Max size label' => 'Max size',
+'Max size help' => 'The maximum allowed size of avatars in bytes (10240 is recommended).',
+
+// E-mail section
+'E-mail subhead' => 'Email',
+'Admin e-mail label' => 'Admin email',
+'Admin e-mail help' => 'The email address of the board administrator.',
+'Webmaster e-mail label' => 'Webmaster email',
+'Webmaster e-mail help' => 'This is the address that all emails sent by the board will be addressed from.',
+'Subscriptions label' => 'Subscriptions',
+'Subscriptions help' => 'Enable users to subscribe to topics (receive email when someone replies).',
+'SMTP address label' => 'SMTP server address',
+'SMTP address help' => 'The address of an external SMTP server to send emails with. You can specify a custom port number if the SMTP server doesn\'t run on the default port 25 (example: mail.myhost.com:3580). Leave blank to use the local mail program.',
+'SMTP username label' => 'SMTP username',
+'SMTP username help' => 'Username for SMTP server. Only enter a username if it is required by the SMTP server (most servers do not require authentication).',
+'SMTP password label' => 'SMTP password',
+'SMTP password help' => 'Password for SMTP server. Only enter a password if it is required by the SMTP server (most servers do not require authentication).',
+'SMTP SSL label' => 'Encrypt SMTP using SSL',
+'SMTP SSL help' => 'Encrypts the connection to the SMTP server using SSL. Should only be used if your SMTP server requires it and your version of PHP supports SSL.',
+
+// Registration Section
+'Registration subhead' => 'Registration',
+'Allow new label' => 'Allow new registrations',
+'Allow new help' => 'Controls whether this board accepts new registrations. Disable only under special circumstances.',
+'Verify label' => 'Verify registrations',
+'Verify help' => 'When enabled, users are emailed a random password when they register. They can then log in and change the password in their profile if they see fit. This feature also requires users to verify new email addresses if they choose to change from the one they registered with. This is an effective way of avoiding registration abuse and making sure that all users have "correct" email addresses in their profiles.',
+'Report new label' => 'Report new registrations',
+'Report new help' => 'If enabled, FluxBB will notify users on the mailing list (see above) when a new user registers in the forums.',
+'Use rules label' => 'User forum rules',
+'Use rules help' => 'When enabled, users must agree to a set of rules when registering (enter text below). The rules will always be available through a link in the navigation table at the top of every page.',
+'Rules label' => 'Enter your rules here',
+'Rules help' => 'Here you can enter any rules or other information that the user must review and accept when registering. If you enabled rules above you have to enter something here, otherwise it will be disabled. This text will not be parsed like regular posts and thus may contain HTML.',
+'E-mail default label' => 'Default email setting',
+'E-mail default help' => 'Choose the default privacy setting for new user registrations.',
+'Display e-mail label' => 'Display email address to other users.',
+'Hide allow form label' => 'Hide email address but allow form e-mail.',
+'Hide both label' => 'Hide email address and disallow form email.',
+
+// Announcement Section
+'Announcement subhead' => 'Announcements',
+'Display announcement label' => 'Display announcement',
+'Display announcement help' => 'Enable this to display the below message in the board.',
+'Announcement message label' => 'Announcement message',
+'Announcement message help' => 'This text will not be parsed like regular posts and thus may contain HTML.',
+
+// Maintenance Section
+'Maintenance subhead' => 'Maintenance',
+'Maintenance mode label' => 'Maintenance mode',
+'Maintenance mode help' => 'When enabled, the board will only be available to administrators. This should be used if the board needs to be taken down temporarily for maintenance. WARNING! Do not log out when the board is in maintenance mode. You will not be able to login again.',
+'Maintenance message label' => 'Maintenance message',
+'Maintenance message help' => 'The message that will be displayed to users when the board is in maintenance mode. If left blank, a default message will be used. This text will not be parsed like regular posts and thus may contain HTML.',
+
+);
diff --git a/lang/English/admin_permissions.php b/lang/English/admin_permissions.php
new file mode 100644
index 0000000..3c3600c
--- /dev/null
+++ b/lang/English/admin_permissions.php
@@ -0,0 +1,36 @@
+ 'Permissions updated. Redirecting …',
+'Permissions head' => 'Permissions',
+'Posting subhead' => 'Posting',
+'BBCode label' => 'BBCode',
+'BBCode help' => 'Allow BBCode in posts (recommended).',
+'Image tag label' => 'Image tag',
+'Image tag help' => 'Allow the BBCode [img][/img] tag in posts.',
+'All caps message label' => 'All caps message',
+'All caps message help' => 'Allow a message to contain only capital letters.',
+'All caps subject label' => 'All caps subject',
+'All caps subject help' => 'Allow a subject to contain only capital letters.',
+'Require e-mail label' => 'Require guest email',
+'Require e-mail help' => 'Require guests to supply an email address when posting.',
+'Signatures subhead' => 'Signatures',
+'BBCode sigs label' => 'BBCodes in signatures',
+'BBCode sigs help' => 'Allow BBCodes in user signatures.',
+'Image tag sigs label' => 'Image tag in signatures',
+'Image tag sigs help' => 'Allow the BBCode [img][/img] tag in user signatures (not recommended).',
+'All caps sigs label' => 'All caps signature',
+'All caps sigs help' => 'Allow a signature to contain only capital letters.',
+'Max sig length label' => 'Maximum signature length',
+'Max sig length help' => 'The maximum number of characters a user signature may contain.',
+'Max sig lines label' => 'Maximum signature lines',
+'Max sig lines help' => 'The maximum number of lines a user signature may contain.',
+'Registration subhead' => 'Registration',
+'Banned e-mail label' => 'Allow banned email addresses',
+'Banned e-mail help' => 'Allow users to register with or change to a banned email address/domain. If left at its default setting (yes), this action will be allowed, but an alert email will be sent to the mailing list (an effective way of detecting multiple registrations).',
+'Duplicate e-mail label' => 'Allow duplicate email addresses',
+'Duplicate e-mail help' => 'Controls whether users should be allowed to register with an email address that another user already has. If allowed, an alert email will be sent to the mailing list if a duplicate is detected.',
+
+);
diff --git a/lang/English/admin_plugin_example.php b/lang/English/admin_plugin_example.php
new file mode 100644
index 0000000..b06158d
--- /dev/null
+++ b/lang/English/admin_plugin_example.php
@@ -0,0 +1,17 @@
+ 'You didn\'t enter anything!',
+'Example plugin title' => 'Example plugin',
+'You said' => 'You said "%s". Great stuff.',
+'Explanation 1' => 'This plugin doesn\'t do anything useful. Hence the name "Example".',
+'Explanation 2' => 'This would be a good spot to talk a little about your plugin. Describe what it does and how it should be used. Be brief, but informative.',
+'Example form title' => 'An example form',
+'Legend text' => 'Enter a piece of text and hit "Show text"!',
+'Text to show' => 'Text to show',
+'Show text button' => 'Show text',
+'Input content' => 'The text you want to display.',
+
+);
diff --git a/lang/English/admin_prune.php b/lang/English/admin_prune.php
new file mode 100644
index 0000000..b7f9030
--- /dev/null
+++ b/lang/English/admin_prune.php
@@ -0,0 +1,23 @@
+ 'Days to prune must be a positive integer value.',
+'No old topics message' => 'There are no topics that are %s days old. Please decrease the value of "Days old" and try again.',
+'Posts pruned redirect' => 'Posts pruned. Redirecting …',
+'Prune head' => 'Prune',
+'Prune subhead' => 'Prune old posts',
+'Days old label' => 'Days old',
+'Days old help' => 'The number of days "old" a topic must be to be pruned. E.g. if you were to enter 30, every topic that didn\'t contain a post dated less than 30 days old would be deleted.',
+'Prune sticky label' => 'Prune sticky topics',
+'Prune sticky help' => 'When enabled sticky topics will also be pruned.',
+'Prune from label' => 'Prune from forum',
+'All forums' => 'All forums',
+'Prune from help' => 'The forum from which you want to prune posts.',
+'Prune info' => 'Use this feature with caution. Pruned posts can never be recovered. For best performance, you should put the forum in %s during pruning.',
+'Confirm prune subhead' => 'Confirm prune posts',
+'Confirm prune info' => 'Are you sure that you want to prune all topics older than %s days from %s (%s topics).',
+'Confirm prune warn' => 'WARNING! Pruning posts deletes them permanently.',
+
+);
diff --git a/lang/English/admin_ranks.php b/lang/English/admin_ranks.php
new file mode 100644
index 0000000..7dca408
--- /dev/null
+++ b/lang/English/admin_ranks.php
@@ -0,0 +1,21 @@
+ 'Minimum posts must be a positive integer value.',
+'Dupe min posts message' => 'There is already a rank with a minimun posts value of %s.',
+'Must enter title message' => 'You must enter a rank title.',
+'Rank added redirect' => 'Rank added. Redirecting …',
+'Rank updated redirect' => 'Rank updated. Redirecting …',
+'Rank removed redirect' => 'Rank removed. Redirecting …',
+'Ranks head' => 'Ranks',
+'Add rank subhead' => 'Add rank',
+'Add rank info' => 'Enter a rank and the minimum number of posts a user must have made to attain the rank. Different ranks cannot have the same value for minimum posts. If a title is set for a user, the title will be displayed instead of any rank. User ranks must be enabled in %s for this to have any effect.',
+'Rank title label' => 'Rank title',
+'Minimum posts label' => 'Minimum posts',
+'Actions label' => 'Actions',
+'Edit remove subhead' => 'Edit/remove ranks',
+'No ranks in list' => 'No ranks in list',
+
+);
diff --git a/lang/English/admin_reports.php b/lang/English/admin_reports.php
new file mode 100644
index 0000000..152bab3
--- /dev/null
+++ b/lang/English/admin_reports.php
@@ -0,0 +1,20 @@
+ 'Report zapped. Redirecting …',
+'New reports head' => 'New reports',
+'Deleted user' => 'Deleted user',
+'Deleted' => 'Deleted',
+'Report subhead' => 'Reported %s',
+'Reported by' => 'Reported by %s',
+'Reason' => 'Reason',
+'Zap' => 'Zap',
+'No new reports' => 'There are no new reports.',
+'Last 10 head' => '10 last zapped reports',
+'NA' => 'N/A',
+'Zapped subhead' => 'Zapped %s by %s',
+'No zapped reports' => 'There are no zapped reports.',
+
+);
\ No newline at end of file
diff --git a/lang/English/admin_users.php b/lang/English/admin_users.php
new file mode 100644
index 0000000..1e21a34
--- /dev/null
+++ b/lang/English/admin_users.php
@@ -0,0 +1,70 @@
+ 'You entered a non-numeric value into a numeric only column.',
+'Invalid date time message' => 'You entered an invalid date/time.',
+'Not verified' => 'Not verified',
+'User search head' => 'User search',
+'User search subhead' => 'Enter search criteria',
+'User search info' => 'Search for users in the database. You can enter one or more terms to search for. Wildcards in the form of asterisks (*) are accepted.',
+'Username label' => 'Username',
+'E-mail address label' => 'Email address',
+'Title label' => 'Title',
+'Real name label' => 'Real name',
+'Website label' => 'Website',
+'Jabber label' => 'Jabber',
+'ICQ label' => 'ICQ',
+'MSN label' => 'MSN Messenger',
+'AOL label' => 'AOL IM',
+'Yahoo label' => 'Yahoo Messenger',
+'Location label' => 'Location',
+'Signature label' => 'Signature',
+'Admin note label' => 'Admin note',
+'Posts more than label' => 'Number of posts greater than',
+'Posts less than label' => 'Number of posts less than',
+'Last post after label' => 'Last post is after',
+'Date help' => '(yyyy-mm-dd hh:mm:ss)',
+'Last post before label' => 'Last post is before',
+'Registered after label' => 'Registered after',
+'Registered before label' => 'Registered before',
+'Order by label' => 'Order by',
+'Order by username' => 'Username',
+'Order by e-mail' => 'Email',
+'Order by posts' => 'Number of posts',
+'Order by last post' => 'Last post',
+'Order by registered' => 'Registered',
+'Ascending' => 'Ascending',
+'Descending' => 'Descending',
+'User group label' => 'User group',
+'All groups' => 'All groups',
+'Unverified users' => 'Unverified users',
+'Submit search' => 'Submit search',
+'IP search head' => 'IP search',
+'IP search subhead' => 'Enter IP to search for',
+'IP address label' => 'IP address',
+'IP address help' => 'The IP address to search for in the post database.',
+'Find IP address' => 'Find IP address',
+
+'Results head' => 'Search Results',
+'Results username head' => 'Username',
+'Results e-mail head' => 'Email',
+'Results title head' => 'Title/Status',
+'Results posts head' => 'Posts',
+'Results admin note head' => 'Admin note',
+'Results actions head' => 'Actions',
+'Results IP address head' => 'IP address',
+'Results last used head' => 'Last used',
+'Results times found head' => 'Times found',
+'Results action head' => 'Action',
+'Results find more link' => 'Find more users for this ip',
+'Results no posts found' => 'There are currently no posts by that user in the forum.',
+'Bad IP message' => 'The supplied IP address is not correctly formatted.',
+'Results view IP link' => 'View IP stats',
+'Results show posts link' => 'Show posts',
+'Results guest' => 'Guest',
+'Results no IP found' => 'The supplied IP address could not be found in the database.',
+'No match' => 'No match'
+
+);
diff --git a/lang/English/common.php b/lang/English/common.php
new file mode 100644
index 0000000..85c276f
--- /dev/null
+++ b/lang/English/common.php
@@ -0,0 +1,169 @@
+ 'ltr', // ltr (Left-To-Right) or rtl (Right-To-Left)
+'lang_identifier' => 'en',
+
+// Number formatting
+'lang_decimal_point' => '.',
+'lang_thousands_sep' => ',',
+
+// Notices
+'Bad request' => 'Bad request. The link you followed is incorrect or outdated.',
+'No view' => 'You do not have permission to view these forums.',
+'No permission' => 'You do not have permission to access this page.',
+'Bad referrer' => 'Bad HTTP_REFERER. You were referred to this page from an unauthorized source. If the problem persists please make sure that \'Base URL\' is correctly set in Admin/Options and that you are visiting the forum by navigating to that URL. More information regarding the referrer check can be found in the FluxBB documentation.',
+'No cookie' => 'You appear to have logged in successfully, however a cookie has not been set. Please check your settings and if applicable, enable cookies for this website.',
+'Pun include error' => 'Unable to process user include %s from template %s. There is no such file in neither the template directory nor in the user include directory.',
+
+// Miscellaneous
+'Announcement' => 'Announcement',
+'Options' => 'Options',
+'Submit' => 'Submit', // "Name" of submit buttons
+'Ban message' => 'You are banned from this forum.',
+'Ban message 2' => 'The ban expires at the end of',
+'Ban message 3' => 'The administrator or moderator that banned you left the following message:',
+'Ban message 4' => 'Please direct any inquiries to the forum administrator at',
+'Never' => 'Never',
+'Today' => 'Today',
+'Yesterday' => 'Yesterday',
+'Info' => 'Info', // A common table header
+'Go back' => 'Go back',
+'Maintenance' => 'Maintenance',
+'Redirecting' => 'Redirecting',
+'Click redirect' => 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you)',
+'on' => 'on', // As in "BBCode is on"
+'off' => 'off',
+'Invalid email' => 'The email address you entered is invalid.',
+'Required' => '(Required)',
+'required field' => 'is a required field in this form.', // For javascript form validation
+'Last post' => 'Last post',
+'by' => 'by', // As in last post by someuser
+'New posts' => 'New posts', // The link that leads to the first new post
+'New posts info' => 'Go to the first new post in this topic.', // The popup text for new posts links
+'Username' => 'Username',
+'Password' => 'Password',
+'Email' => 'Email',
+'Send email' => 'Send email',
+'Moderated by' => 'Moderated by',
+'Registered' => 'Registered',
+'Subject' => 'Subject',
+'Message' => 'Message',
+'Topic' => 'Topic',
+'Forum' => 'Forum',
+'Posts' => 'Posts',
+'Replies' => 'Replies',
+'Pages' => 'Pages:',
+'Page' => 'Page %s',
+'BBCode' => 'BBCode:', // You probably shouldn't change this
+'img tag' => '[img] tag:',
+'Smilies' => 'Smilies:',
+'and' => 'and',
+'Image link' => 'image', // This is displayed (i.e. ) instead of images when "Show images" is disabled in the profile
+'wrote' => 'wrote:', // For [quote]'s
+'Mailer' => 'Mailer', // As in "MyForums Mailer" in the signature of outgoing emails
+'Important information' => 'Important information',
+'Write message legend' => 'Write your message and submit',
+'Previous' => 'Previous',
+'Next' => 'Next',
+'Spacer' => '…', // Ellipsis for paginate
+
+// Title
+'Title' => 'Title',
+'Member' => 'Member', // Default title
+'Moderator' => 'Moderator',
+'Administrator' => 'Administrator',
+'Banned' => 'Banned',
+'Guest' => 'Guest',
+
+// Stuff for include/parser.php
+'BBCode error no opening tag' => '[/%1$s] was found without a matching [%1$s]',
+'BBCode error invalid nesting' => '[%1$s] was opened within [%2$s], this is not allowed',
+'BBCode error invalid self-nesting' => '[%s] was opened within itself, this is not allowed',
+'BBCode error no closing tag' => '[%1$s] was found without a matching [/%1$s]',
+'BBCode error empty attribute' => '[%s] tag had an empty attribute section',
+'BBCode code problem' => 'There is a problem with your [code] tags',
+'BBCode list size error' => 'Your list was too long to parse, please make it smaller!',
+
+// Stuff for the navigator (top of every page)
+'Index' => 'Index',
+'User list' => 'User list',
+'Rules' => 'Rules',
+'Search' => 'Search',
+'Register' => 'Register',
+'Login' => 'Login',
+'Not logged in' => 'You are not logged in.',
+'Profile' => 'Profile',
+'Logout' => 'Logout',
+'Logged in as' => 'Logged in as',
+'Admin' => 'Administration',
+'Last visit' => 'Last visit: %s',
+'Show new posts' => 'Show new posts since last visit',
+'Mark all as read' => 'Mark all topics as read',
+'Mark forum read' => 'Mark this forum as read',
+'Title separator' => ' / ',
+
+// Stuff for the page footer
+'Board footer' => 'Board footer',
+'Search links' => 'Search links',
+'Show recent posts' => 'Show recent posts',
+'Show unanswered posts' => 'Show unanswered posts',
+'Show your posts' => 'Show your posts',
+'Show subscriptions' => 'Show your subscribed topics',
+'Jump to' => 'Jump to',
+'Go' => ' Go ', // Submit button in forum jump
+'Moderate topic' => 'Moderate topic',
+'Move topic' => 'Move topic',
+'Open topic' => 'Open topic',
+'Close topic' => 'Close topic',
+'Unstick topic' => 'Unstick topic',
+'Stick topic' => 'Stick topic',
+'Moderate forum' => 'Moderate forum',
+'Powered by' => 'Powered by %s',
+
+// Debug information
+'Debug table' => 'Debug information',
+'Querytime' => 'Generated in %1$s seconds, %2$s queries executed',
+'Memory usage' => 'Memory usage: %1$s',
+'Peak usage' => '(Peak: %1$s)',
+'Query times' => 'Time (s)',
+'Query' => 'Query',
+'Total query time' => 'Total query time: %s',
+
+// Email related notifications
+'New user notification' => 'Alert - New registration',
+'New user message' => 'User \'%s\' registered in the forums at %s',
+'Banned email notification' => 'Alert - Banned email detected',
+'Banned email register message' => 'User \'%s\' registered with banned email address: %s',
+'Banned email change message' => 'User \'%s\' changed to banned email address: %s',
+'Banned email post message' => 'User \'%s\' posted with banned email address: %s',
+'Duplicate email notification' => 'Alert - Duplicate email detected',
+'Duplicate email register message' => 'User \'%s\' registered with an email address that also belongs to: %s',
+'Duplicate email change message' => 'User \'%s\' changed to an email address that also belongs to: %s',
+'Report notification' => 'Report(%d) - \'%s\'',
+'Report message 1' => 'User \'%s\' has reported the following message: %s',
+'Report message 2' => 'Reason: %s',
+
+'User profile' => 'User profile: %s',
+'Post URL' => 'Post URL: %s',
+'Email signature' => 'Forum Mailer'."\n".'(Do not reply to this message)',
+
+// For extern.php RSS feed
+'RSS description' => 'The most recent topics at %s.',
+'RSS description topic' => 'The most recent posts in %s.',
+'RSS reply' => 'Re: ', // The topic subject will be appended to this string (to signify a reply)
+'RSS active topics feed' => 'RSS active topics feed',
+'Atom active topics feed' => 'Atom active topics feed',
+'RSS forum feed' => 'RSS forum feed',
+'Atom forum feed' => 'Atom forum feed',
+'RSS topic feed' => 'RSS topic feed',
+'Atom topic feed' => 'Atom topic feed',
+
+// Admin related stuff in the header
+'New reports' => 'There are new reports',
+'Maintenance mode enabled' => 'Maintenance mode is enabled!',
+
+);
diff --git a/lang/English/delete.php b/lang/English/delete.php
new file mode 100644
index 0000000..61599d2
--- /dev/null
+++ b/lang/English/delete.php
@@ -0,0 +1,16 @@
+ 'Delete post',
+'Warning' => 'You are about to permanently delete this post.',
+'Topic warning' => 'Warning! This is the first post in the topic, the whole topic will be permanently deleted.',
+'Delete info' => 'The post you have chosen to delete is set out below for you to review before proceeding.',
+'Reply by' => 'Reply by %s - %s',
+'Topic by' => 'Topic started by %s - %s',
+'Delete' => 'Delete', // The submit button
+'Post del redirect' => 'Post deleted. Redirecting …',
+'Topic del redirect' => 'Topic deleted. Redirecting …'
+
+);
\ No newline at end of file
diff --git a/lang/English/forum.php b/lang/English/forum.php
new file mode 100644
index 0000000..42111da
--- /dev/null
+++ b/lang/English/forum.php
@@ -0,0 +1,14 @@
+ 'Post new topic',
+'Views' => 'Views',
+'Moved' => 'Moved:',
+'Sticky' => 'Sticky:',
+'Closed' => 'Closed:',
+'Empty forum' => 'Forum is empty.',
+'Mod controls' => 'Moderator controls'
+
+);
diff --git a/lang/English/help.php b/lang/English/help.php
new file mode 100644
index 0000000..47b5e0a
--- /dev/null
+++ b/lang/English/help.php
@@ -0,0 +1,59 @@
+ 'Help',
+'produces' => 'produces',
+
+'BBCode' => 'BBCode',
+'BBCode info 1' => 'BBCode is a collection of formatting tags that are used to change the look of text in this forum. BBCode is based on the same principal as, and is very similar to, HTML. Below is a list of all the available BBCodes and instructions on how to use them.',
+'BBCode info 2' => 'Administrators have the ability to enable or disable BBCode. You can tell if BBCode is enabled or disabled out in the left margin whenever you post a message or edit your signature.',
+
+'Text style' => 'Text style',
+'Text style info' => 'The following tags change the appearance of text:',
+'Bold text' => 'Bold text',
+'Underlined text' => 'Underlined text',
+'Italic text' => 'Italic text',
+'Strike-through text' => 'Strike-through text',
+'Red text' => 'Red text',
+'Blue text' => 'Blue text',
+'Heading text' => 'Heading text',
+'Deleted text' => 'Deleted text',
+'Inserted text' => 'Inserted text',
+'Emphasised text' => 'Emphasised text',
+
+'Links and images' => 'Links and images',
+'Links info' => 'You can create links to other documents or to email addresses using the following tags:',
+'My email address' => 'My email address',
+'Images info' => 'If you want to display an image you can use the img tag. The text appearing after the "=" sign in the opening tag is used for the alt attribute and should be included whenever possible.',
+
+'Quotes' => 'Quotes',
+'Quotes info' => 'If you want to quote someone, you should use the quote tag.',
+'Quotes info 2' => 'If you don\'t want to quote anyone in particular, you can use the quote tag without specifying a name.',
+'Quote text' => 'This is the text i want to quote.',
+'produces quote box' => 'produces a quote box like this:',
+'quote note' => 'Note: If a username contains the characters [ or ] you can enclose it in quote marks.',
+
+'Code' => 'Code',
+'Code info' => 'When displaying source code you should make sure that you use the code tag. Text displayed with the code tag will use a monospaced font and will not be affected by other tags.',
+'Code text' => 'This is some code.',
+'produces code box' => 'produces a code box like this:',
+
+'Nested tags' => 'Nested tags',
+'Nested tags info' => 'BBCode can be nested to create more advanced formatting. For example:',
+'Bold, underlined text' => 'Bold, underlined text',
+
+'Lists' => 'Lists',
+'List info' => 'To create a list you can use the list tag. You can create 3 types of lists using the list tag.',
+'List text 1' => 'Example list item 1.',
+'List text 2' => 'Example list item 2.',
+'List text 3' => 'Example list item 3.',
+'produces list' => 'produces a bulleted list.',
+'produces decimal list' => 'produces a numbered list.',
+'produces alpha list' => 'produces an alphabetically labelled list.',
+
+'Smilies' => 'Smilies',
+'Smilies info' => 'If you like (and if it is enabled), the forum can convert a series of smilies to images representations of that smiley. This forum recognizes the following smilies and replaces them with images:'
+
+);
diff --git a/lang/English/index.html b/lang/English/index.html
new file mode 100644
index 0000000..89337b2
--- /dev/null
+++ b/lang/English/index.html
@@ -0,0 +1 @@
+..
diff --git a/lang/English/index.php b/lang/English/index.php
new file mode 100644
index 0000000..0ed222a
--- /dev/null
+++ b/lang/English/index.php
@@ -0,0 +1,20 @@
+ 'Topics',
+'Link to' => 'Link to:', // As in "Link to: http://fluxbb.org/"
+'Empty board' => 'Board is empty.',
+'Newest user' => 'Newest registered user: %s',
+'Users online' => 'Registered users online: %s',
+'Guests online' => 'Guests online: %s',
+'No of users' => 'Total number of registered users: %s',
+'No of topics' => 'Total number of topics: %s',
+'No of posts' => 'Total number of posts: %s',
+'Online' => 'Online:', // As in "Online: User A, User B etc."
+'Board info' => 'Board information',
+'Board stats' => 'Board statistics',
+'User info' => 'User information'
+
+);
diff --git a/lang/English/login.php b/lang/English/login.php
new file mode 100644
index 0000000..244ee06
--- /dev/null
+++ b/lang/English/login.php
@@ -0,0 +1,26 @@
+ 'Wrong username and/or password.',
+'Forgotten pass' => 'Forgotten your password?',
+'Login redirect' => 'Logged in successfully. Redirecting …',
+'Logout redirect' => 'Logged out. Redirecting …',
+'No email match' => 'There is no user registered with the email address',
+'Request pass' => 'Request password',
+'Request pass legend' => 'Enter the email address with which you registered',
+'Request pass info' => 'A new password together with a link to activate the new password will be sent to that address.',
+'Not registered' => 'Not registered yet?',
+'Login legend' => 'Enter your username and password below',
+'Remember me' => 'Log me in automatically each time I visit.',
+'Login info' => 'If you have not registered or have forgotten your password click on the appropriate link below.',
+'New password errors' => 'Password request error',
+'New passworderrors info' => 'The following error needs to be corrected before a new password can be sent:',
+
+// Forget password mail stuff
+'Forget mail' => 'An email has been sent to the specified address with instructions on how to change your password. If it does not arrive you can contact the forum administrator at',
+'Email flood' => 'This account has already requested a password reset in the past hour. Please wait a while before requesting a new password again.'
+
+);
diff --git a/lang/English/mail_templates/activate_email.tpl b/lang/English/mail_templates/activate_email.tpl
new file mode 100644
index 0000000..f17066f
--- /dev/null
+++ b/lang/English/mail_templates/activate_email.tpl
@@ -0,0 +1,12 @@
+Subject: Change email address requested
+
+Hello ,
+
+You have requested to have a new email address assigned to your account in the discussion forum at . If you didn't request this or if you don't want to change your email address you should just ignore this message. Only if you visit the activation page below will your email address be changed. In order for the activation page to work, you must be logged in to the forum.
+
+To change your email address, please visit the following page:
+
+
+--
+
+(Do not reply to this message)
diff --git a/lang/English/mail_templates/activate_password.tpl b/lang/English/mail_templates/activate_password.tpl
new file mode 100644
index 0000000..33b2b3e
--- /dev/null
+++ b/lang/English/mail_templates/activate_password.tpl
@@ -0,0 +1,14 @@
+Subject: New password requested
+
+Hello ,
+
+You have requested to have a new password assigned to your account in the discussion forum at . If you didn't request this or if you don't want to change your password you should just ignore this message. Only if you visit the activation page below will your password be changed.
+
+Your new password is:
+
+To change your password, please visit the following page:
+
+
+--
+
+(Do not reply to this message)
diff --git a/lang/English/mail_templates/form_email.tpl b/lang/English/mail_templates/form_email.tpl
new file mode 100644
index 0000000..b862422
--- /dev/null
+++ b/lang/English/mail_templates/form_email.tpl
@@ -0,0 +1,13 @@
+Subject:
+
+ from has sent you a message. You can reply to by replying to this email.
+
+The message reads as follows:
+-----------------------------------------------------------------------
+
+
+
+-----------------------------------------------------------------------
+
+--
+
diff --git a/lang/English/mail_templates/index.html b/lang/English/mail_templates/index.html
new file mode 100644
index 0000000..89337b2
--- /dev/null
+++ b/lang/English/mail_templates/index.html
@@ -0,0 +1 @@
+..
diff --git a/lang/English/mail_templates/new_reply.tpl b/lang/English/mail_templates/new_reply.tpl
new file mode 100644
index 0000000..e9dab0b
--- /dev/null
+++ b/lang/English/mail_templates/new_reply.tpl
@@ -0,0 +1,11 @@
+Subject: Reply to topic:
+
+ has replied to the topic to which you are subscribed. There may be more new replies, but this is the only notification you will receive until you visit the board again.
+
+The post is located at
+
+You can unsubscribe by going to
+
+--
+
+(Do not reply to this message)
diff --git a/lang/English/mail_templates/new_reply_full.tpl b/lang/English/mail_templates/new_reply_full.tpl
new file mode 100644
index 0000000..7231145
--- /dev/null
+++ b/lang/English/mail_templates/new_reply_full.tpl
@@ -0,0 +1,18 @@
+Subject: Reply to topic:
+
+ has replied to the topic to which you are subscribed. There may be more new replies, but this is the only notification you will receive until you visit the board again.
+
+The message reads as follows:
+-----------------------------------------------------------------------
+
+
+
+-----------------------------------------------------------------------
+
+The post is located at
+
+You can unsubscribe by going to
+
+--
+
+(Do not reply to this message)
diff --git a/lang/English/mail_templates/welcome.tpl b/lang/English/mail_templates/welcome.tpl
new file mode 100644
index 0000000..0110042
--- /dev/null
+++ b/lang/English/mail_templates/welcome.tpl
@@ -0,0 +1,12 @@
+Subject: Welcome to !
+
+Thank you for registering in the forums at . Your account details are:
+
+Username:
+Password:
+
+Login at to activate the account.
+
+--
+
+(Do not reply to this message)
diff --git a/lang/English/misc.php b/lang/English/misc.php
new file mode 100644
index 0000000..9ccd4b2
--- /dev/null
+++ b/lang/English/misc.php
@@ -0,0 +1,90 @@
+ 'All topics and forums have been marked as read. Redirecting …',
+'Mark forum read redirect' => 'All topics in the specified forum have been marked as read. Redirecting …',
+
+// Send email
+'Form email disabled' => 'The user you are trying to send an email to has disabled form email.',
+'No email subject' => 'You must enter a subject.',
+'No email message' => 'You must enter a message.',
+'Too long email message' => 'Messages cannot be longer than 65535 characters (64 KB).',
+'Email flood' => 'At least %s seconds have to pass between sent emails. Please wait a while and try sending again.',
+'Email sent redirect' => 'Email sent. Redirecting …',
+'Send email to' => 'Send email to',
+'Email subject' => 'Subject',
+'Email message' => 'Message',
+'Email disclosure note' => 'Please note that by using this form, your email address will be disclosed to the recipient.',
+'Write email' => 'Write and submit your email message',
+
+// Report
+'No reason' => 'You must enter a reason.',
+'Report flood' => 'At least %s seconds have to pass between reports. Please wait a while and try sending again.',
+'Report redirect' => 'Post reported. Redirecting …',
+'Report post' => 'Report post',
+'Reason' => 'Reason',
+'Reason desc' => 'Please enter a short reason why you are reporting this post',
+
+// Subscriptions
+'Already subscribed' => 'You are already subscribed to this topic.',
+'Subscribe redirect' => 'Your subscription has been added. Redirecting …',
+'Not subscribed' => 'You are not subscribed to this topic.',
+'Unsubscribe redirect' => 'Your subscription has been removed. Redirecting …',
+
+// General forum and topic moderation
+'Moderate' => 'Moderate',
+'Select' => 'Select', // the header of a column of checkboxes
+'Move' => 'Move',
+'Split' => 'Split',
+'Delete' => 'Delete',
+'Merge' => 'Merge',
+
+// Moderate forum
+'Open' => 'Open',
+'Close' => 'Close',
+'Move topic' => 'Move topic',
+'Move topics' => 'Move topics',
+'Move legend' => 'Select destination of move',
+'Move to' => 'Move to',
+'Nowhere to move' => 'There are no forums into which you can move topics.',
+'Leave redirect' => 'Leave redirect topic(s)',
+'Move topic redirect' => 'Topic moved. Redirecting …',
+'Move topics redirect' => 'Topics moved. Redirecting …',
+'Confirm delete legend' => 'Please confirm deletion',
+'Delete topics' => 'Delete topics',
+'Delete topics comply' => 'Are you sure you want to delete the selected topics?',
+'Delete topics redirect' => 'Topics deleted. Redirecting …',
+'Open topic redirect' => 'Topic opened. Redirecting …',
+'Open topics redirect' => 'Topics opened. Redirecting …',
+'Close topic redirect' => 'Topic closed. Redirecting …',
+'Close topics redirect' => 'Topics closed. Redirecting …',
+'No topics selected' => 'You must select at least one topic for move/delete/open/close.',
+'Not enough topics selected' => 'You must select at least two topics for merge.',
+'Stick topic redirect' => 'Topic sticked. Redirecting …',
+'Unstick topic redirect' => 'Topic unsticked. Redirecting …',
+'Merge topics' => 'Merge topics',
+'Merge topics redirect' => 'Topics merged. Redirecting …',
+'Confirm merge legend' => 'Please confirm merge',
+'New subject' => 'New subject',
+
+// Split multiple posts in topic
+'Confirm split legend' => 'Please confirm split of selected posts.',
+'Split posts' => 'Split posts',
+'Split posts comply' => 'Are you sure you want to split the selected posts?',
+'Split posts redirect' => 'Posts have been split. Redirecting …',
+
+// Delete multiple posts in topic
+'Delete posts' => 'Delete posts',
+'Cannot select first' => 'First post cannot be selected for split/delete.',
+'Delete posts comply' => 'Are you sure you want to delete the selected posts?',
+'Delete posts redirect' => 'Posts deleted. Redirecting …',
+'No posts selected' => 'You must select at least one post for split/delete.',
+
+// Get host
+'Host info 1' => 'The IP address is: %s',
+'Host info 2' => 'The host name is: %s',
+'Show more users' => 'Show more users for this IP',
+
+);
diff --git a/lang/English/post.php b/lang/English/post.php
new file mode 100644
index 0000000..5c8ea37
--- /dev/null
+++ b/lang/English/post.php
@@ -0,0 +1,36 @@
+ 'Topics must contain a subject.',
+'Too long subject' => 'Subjects cannot be longer than 70 characters.',
+'No message' => 'You must enter a message.',
+'Too long message' => 'Posts cannot be longer that 65535 characters (64 KB).',
+'All caps subject' => 'Subjects cannot contain only capital letters.',
+'All caps message' => 'Posts cannot contain only capital letters.',
+
+// Posting
+'Post errors' => 'Post errors',
+'Post errors info' => 'The following errors need to be corrected before the message can be posted:',
+'Post preview' => 'Post preview',
+'Guest name' => 'Name', // For guests (instead of Username)
+'Post redirect' => 'Post entered. Redirecting …',
+'Post a reply' => 'Post a reply',
+'Post new topic' => 'Post new topic',
+'Hide smilies' => 'Never show smilies as icons for this post',
+'Subscribe' => 'Subscribe to this topic',
+'Stay subscribed' => 'Stay subscribed to this topic',
+'Topic review' => 'Topic review (newest first)',
+'Flood start' => 'At least',
+'flood end' => 'seconds have to pass between posts. Please wait a little while and try posting again.',
+'Preview' => 'Preview', // submit button to preview message
+
+// Edit post
+'Edit post legend' => 'Edit the post and submit changes',
+'Silent edit' => 'Silent edit (don\'t display "Edited by ..." in topic view)',
+'Edit post' => 'Edit post',
+'Edit redirect' => 'Post updated. Redirecting …'
+
+);
diff --git a/lang/English/prof_reg.php b/lang/English/prof_reg.php
new file mode 100644
index 0000000..9a69b41
--- /dev/null
+++ b/lang/English/prof_reg.php
@@ -0,0 +1,81 @@
+ 'Enter a valid email address',
+'Email legend 2' => 'Enter and confirm a valid email address',
+'Localisation legend' => 'Set your localisation options',
+'Time zone' => 'Time zone',
+'Time zone info' => 'For the forum to display times correctly you must select your local time zone. If Daylight Savings Time is in effect you should also check the option provided which will advance times by 1 hour.',
+'DST' => 'Daylight Savings Time is in effect (advance time by 1 hour).',
+'Time format' => 'Time format',
+'Date format' => 'Date format',
+'Default' => 'Default',
+'Language' => 'Language',
+'Email setting info' => 'Select whether you want your email address to be viewable to other users or not and if you want other users to be able to send you email via the forum (form email) or not.',
+'Email setting 1' => 'Display your email address.',
+'Email setting 2' => 'Hide your email address but allow form email.',
+'Email setting 3' => 'Hide your email address and disallow form email.',
+'Privacy options legend' => 'Set your privacy options',
+'Confirm pass' => 'Confirm password',
+
+'Username too short' => 'Usernames must be at least 2 characters long. Please choose another (longer) username.',
+'Username too long' => 'Usernames must not be more than 25 characters long. Please choose another (shorter) username.',
+'Username guest' => 'The username guest is reserved. Please choose another username.',
+'Username IP' => 'Usernames may not be in the form of an IP address. Please choose another username.',
+'Username reserved chars' => 'Usernames may not contain all the characters \', " and [ or ] at once. Please choose another username.',
+'Username BBCode' => 'Usernames may not contain any of the text formatting tags (BBCode) that the forum uses. Please choose another username.',
+'Banned username' => 'The username you entered is banned in this forum. Please choose another username.',
+'Pass too short' => 'Passwords must be at least 4 characters long. Please choose another (longer) password.',
+'Pass not match' => 'Passwords do not match.',
+'Banned email' => 'The email address you entered is banned in this forum. Please choose another email address.',
+'Dupe email' => 'Someone else is already registered with that email address. Please choose another email address.',
+'Sig too long' => 'Signatures cannot be longer than',
+'characters' => 'characters',
+'Sig too many lines' => 'Signatures cannot have more than',
+'lines' => 'lines',
+'Bad ICQ' => 'You entered an invalid ICQ UIN. Please go back and correct.',
+
+'UTC-12:00' => '(UTC-12:00) International Date Line West',
+'UTC-11:00' => '(UTC-11:00) Niue, Samoa',
+'UTC-10:00' => '(UTC-10:00) Hawaii-Aleutian, Cook Island',
+'UTC-09:30' => '(UTC-09:30) Marquesas Islands',
+'UTC-09:00' => '(UTC-09:00) Alaska, Gambier Island',
+'UTC-08:30' => '(UTC-08:30) Pitcairn Islands',
+'UTC-08:00' => '(UTC-08:00) Pacific',
+'UTC-07:00' => '(UTC-07:00) Mountain',
+'UTC-06:00' => '(UTC-06:00) Central',
+'UTC-05:00' => '(UTC-05:00) Eastern',
+'UTC-04:00' => '(UTC-04:00) Atlantic',
+'UTC-03:30' => '(UTC-03:30) Newfoundland',
+'UTC-03:00' => '(UTC-03:00) Amazon, Central Greenland',
+'UTC-02:00' => '(UTC-02:00) Mid-Atlantic',
+'UTC-01:00' => '(UTC-01:00) Azores, Cape Verde, Eastern Greenland',
+'UTC' => '(UTC) Western European, Greenwich',
+'UTC+01:00' => '(UTC+01:00) Central European, West African',
+'UTC+02:00' => '(UTC+02:00) Eastern European, Central African',
+'UTC+03:00' => '(UTC+03:00) Moscow, Eastern African',
+'UTC+03:30' => '(UTC+03:30) Iran',
+'UTC+04:00' => '(UTC+04:00) Gulf, Samara',
+'UTC+04:30' => '(UTC+04:30) Afghanistan',
+'UTC+05:00' => '(UTC+05:00) Pakistan, Yekaterinburg',
+'UTC+05:30' => '(UTC+05:30) India, Sri Lanka',
+'UTC+05:45' => '(UTC+05:45) Nepal',
+'UTC+06:00' => '(UTC+06:00) Bangladesh, Bhutan, Novosibirsk',
+'UTC+06:30' => '(UTC+06:30) Cocos Islands, Myanmar',
+'UTC+07:00' => '(UTC+07:00) Indochina, Krasnoyarsk',
+'UTC+08:00' => '(UTC+08:00) Greater China, Australian Western, Irkutsk',
+'UTC+08:45' => '(UTC+08:45) Southeastern Western Australia',
+'UTC+09:00' => '(UTC+09:00) Japan, Korea, Chita',
+'UTC+09:30' => '(UTC+09:30) Australian Central',
+'UTC+10:00' => '(UTC+10:00) Australian Eastern, Vladivostok',
+'UTC+10:30' => '(UTC+10:30) Lord Howe',
+'UTC+11:00' => '(UTC+11:00) Solomon Island, Magadan',
+'UTC+11:30' => '(UTC+11:30) Norfolk Island',
+'UTC+12:00' => '(UTC+12:00) New Zealand, Fiji, Kamchatka',
+'UTC+12:45' => '(UTC+12:45) Chatham Islands',
+'UTC+13:00' => '(UTC+13:00) Tonga, Phoenix Islands',
+'UTC+14:00' => '(UTC+14:00) Line Islands'
+
+);
diff --git a/lang/English/profile.php b/lang/English/profile.php
new file mode 100644
index 0000000..ef6a98c
--- /dev/null
+++ b/lang/English/profile.php
@@ -0,0 +1,140 @@
+ 'Profile menu',
+'Section essentials' => 'Essentials',
+'Section personal' => 'Personal',
+'Section messaging' => 'Messaging',
+'Section personality' => 'Personality',
+'Section display' => 'Display',
+'Section privacy' => 'Privacy',
+'Section admin' => 'Administration',
+
+// Miscellaneous
+'Username and pass legend' => 'Enter your username and password',
+'Personal details legend' => 'Enter your personal details',
+'Contact details legend' => 'Enter your messaging details',
+'User activity' => 'User activity',
+'Paginate info' => 'Enter the number of topics and posts you wish to view on each page.',
+
+// Password stuff
+'Pass key bad' => 'The specified password activation key was incorrect or has expired. Please re-request a new password. If that fails, contact the forum administrator at',
+'Pass updated' => 'Your password has been updated. You can now login with your new password.',
+'Pass updated redirect' => 'Password updated. Redirecting …',
+'Wrong pass' => 'Wrong old password.',
+'Change pass' => 'Change password',
+'Change pass legend' => 'Enter and confirm your new password',
+'Old pass' => 'Old password',
+'New pass' => 'New password',
+'Confirm new pass' => 'Confirm new password',
+'Pass info' => 'Passwords must be at least 4 characters long. Passwords are case sensitive.',
+
+// Email stuff
+'Email key bad' => 'The specified email activation key was incorrect or has expired. Please re-request change of email address. If that fails, contact the forum administrator at',
+'Email updated' => 'Your email address has been updated.',
+'Activate email sent' => 'An email has been sent to the specified address with instructions on how to activate the new email address. If it doesn\'t arrive you can contact the forum administrator at',
+'Email legend' => 'Enter your new email address',
+'Email instructions' => 'An email will be sent to your new address with an activation link. You must click the link in the email you receive to activate the new address.',
+'Change email' => 'Change email address',
+'New email' => 'New email',
+
+// Avatar upload stuff
+'Avatars disabled' => 'The administrator has disabled avatar support.',
+'Too large ini' => 'The selected file was too large to upload. The server didn\'t allow the upload.',
+'Partial upload' => 'The selected file was only partially uploaded. Please try again.',
+'No tmp directory' => 'PHP was unable to save the uploaded file to a temporary location.',
+'No file' => 'You did not select a file for upload.',
+'Bad type' => 'The file you tried to upload is not of an allowed type. Allowed types are gif, jpeg and png.',
+'Too wide or high' => 'The file you tried to upload is wider and/or higher than the maximum allowed',
+'Too large' => 'The file you tried to upload is larger than the maximum allowed',
+'pixels' => 'pixels',
+'bytes' => 'bytes',
+'Move failed' => 'The server was unable to save the uploaded file. Please contact the forum administrator at',
+'Unknown failure' => 'An unknown error occurred. Please try again.',
+'Avatar upload redirect' => 'Avatar uploaded. Redirecting …',
+'Avatar deleted redirect' => 'Avatar deleted. Redirecting …',
+'Avatar desc' => 'An avatar is a small image that will be displayed under your username in your posts. It must not be any bigger than',
+'Upload avatar' => 'Upload avatar',
+'Upload avatar legend' => 'Enter an avatar file to upload',
+'Delete avatar' => 'Delete avatar', // only for admins
+'File' => 'File',
+'Upload' => 'Upload', // submit button
+
+// Form validation stuff
+'Forbidden title' => 'The title you entered contains a forbidden word. You must choose a different title.',
+'Profile redirect' => 'Profile updated. Redirecting …',
+
+// Profile display stuff
+'Users profile' => '%s\'s profile',
+'Unknown' => '(Unknown)', // This is displayed when a user hasn't filled out profile field (e.g. Location)
+'Private' => '(Private)', // This is displayed when a user does not want to receive emails
+'No avatar' => '(No avatar)',
+'Username info' => 'Username: %s',
+'Email info' => 'Email: %s',
+'Posts info' => 'Posts: %s',
+'Registered info' => 'Registered: %s',
+'Last post info' => 'Last post: %s',
+'Show posts' => 'Show all posts',
+'Realname' => 'Real name',
+'Location' => 'Location',
+'Website' => 'Website',
+'Jabber' => 'Jabber',
+'ICQ' => 'ICQ',
+'MSN' => 'MSN Messenger',
+'AOL IM' => 'AOL IM',
+'Yahoo' => 'Yahoo! Messenger',
+'Avatar' => 'Avatar',
+'Signature' => 'Signature',
+'Sig max size' => 'Max length: %s characters / Max lines: %s',
+'Avatar legend' => 'Set your avatar display options',
+'Avatar info' => 'An avatar is a small image that will be displayed with all your posts. You can upload an avatar by clicking the link below.',
+'Change avatar' => 'Change avatar',
+'Signature legend' => 'Compose your signature',
+'Signature info' => 'A signature is a small piece of text that is attached to your posts. In it, you can enter just about anything you like. Perhaps you would like to enter your favourite quote or your star sign. It\'s up to you! In your signature you can use BBCode if it is allowed in this particular forum. You can see the features that are allowed/enabled listed below whenever you edit your signature.',
+'Sig preview' => 'Current signature preview:',
+'No sig' => 'No signature currently stored in profile.',
+'Signature quote/code/list/h' => 'The quote, code, list, and heading BBCodes are not allowed in signatures.',
+'Topics per page' => 'Topics',
+'Posts per page' => 'Posts',
+'Leave blank' => 'Leave blank to use forum default.',
+'Subscription legend' => 'Set your subscription options',
+'Notify full' => 'Include a plain text version of new posts in subscription notification emails.',
+'Auto notify full' => 'Automatically subscribe to every topic you post in.',
+'Show smilies' => 'Show smilies as graphic icons.',
+'Show images' => 'Show images in posts.',
+'Show images sigs' => 'Show images in user signatures.',
+'Show avatars' => 'Show user avatars in posts.',
+'Show sigs' => 'Show user signatures.',
+'Style legend' => 'Select your preferred style',
+'Styles' => 'Styles',
+'Admin note' => 'Admin note',
+'Pagination legend' => 'Enter your pagination options',
+'Post display legend' => 'Set your options for viewing posts',
+'Post display info' => 'If you are on a slow connection, disabling these options, particularly showing images in posts and signatures, will make pages load faster.',
+'Instructions' => 'When you update your profile, you will be redirected back to this page.',
+
+// Administration stuff
+'Group membership legend' => 'Choose user group',
+'Save' => 'Save',
+'Set mods legend' => 'Set moderator access',
+'Moderator in info' => 'Choose which forums this user should be allowed to moderate. Note: This only applies to moderators. Administrators always have full permissions in all forums.',
+'Update forums' => 'Update forums',
+'Delete ban legend' => 'Delete (administrators only) or ban user',
+'Delete user' => 'Delete user',
+'Ban user' => 'Ban user',
+'Confirm delete legend' => 'Important: read before deleting user',
+'Confirm delete user' => 'Confirm delete user',
+'Confirmation info' => 'Please confirm that you want to delete the user', // the username will be appended to this string
+'Delete warning' => 'Warning! Deleted users and/or posts cannot be restored. If you choose not to delete the posts made by this user, the posts can only be deleted manually at a later time.',
+'Delete posts' => 'Delete any posts and topics this user has made.',
+'Delete' => 'Delete', // submit button (confirm user delete)
+'User delete redirect' => 'User deleted. Redirecting …',
+'Group membership redirect' => 'Group membership saved. Redirecting …',
+'Update forums redirect' => 'Forum moderator rights updated. Redirecting …',
+'Ban redirect' => 'Redirecting …',
+'No delete admin message' => 'Administrators cannot be deleted. In order to delete this user, you must first move him/her to a different user group.',
+
+);
diff --git a/lang/English/register.php b/lang/English/register.php
new file mode 100644
index 0000000..c3e24df
--- /dev/null
+++ b/lang/English/register.php
@@ -0,0 +1,37 @@
+ 'This forum is not accepting new registrations.',
+'Reg cancel redirect' => 'Registration cancelled. Redirecting …',
+'Forum rules' => 'Forum rules',
+'Rules legend' => 'You must agree to the following in order to register',
+'Registration flood' => 'A new user was registered with the same IP address as you within the last hour. To prevent registration flooding, at least an hour has to pass between registrations from the same IP. Sorry for the inconvenience.',
+'Agree' => 'Agree',
+'Cancel' => 'Cancel',
+'Register' => 'Register',
+
+// Form validation stuff (some of these are also used in post.php)
+'Registration errors' => 'Registration errors',
+'Registration errors info' => 'The following errors need to be corrected before you can register:',
+'Username censor' => 'The username you entered contains one or more censored words. Please choose a different username.',
+'Username dupe 1' => 'Someone is already registered with the username',
+'Username dupe 2' => 'The username you entered is too similar. The username must differ from that by at least one alphanumerical character (a-z or 0-9). Please choose a different username.',
+'Email not match' => 'Email addresses do not match.',
+
+// Registration email stuff
+'Reg email' => 'Thank you for registering. Your password has been sent to the specified address. If it doesn\'t arrive you can contact the forum administrator at',
+'Reg complete' => 'Registration complete. Logging in and redirecting …',
+
+// Register info
+'Desc 1' => 'Registration will grant you access to a number of features and capabilities otherwise unavailable. These functions include the ability to edit and delete posts, design your own signature that accompanies your posts and much more. If you have any questions regarding this forum you should ask an administrator.',
+'Desc 2' => 'Below is a form you must fill out in order to register. Once you are registered you should visit your profile and review the different settings you can change. The fields below only make up a small part of all the settings you can alter in your profile.',
+'Username legend' => 'Please enter a username between 2 and 25 characters long',
+'Pass legend' => 'Please enter and confirm your chosen password',
+'Pass info' => 'Passwords must be at least 4 characters long. Passwords are case sensitive.',
+'Email info' => 'You must enter a valid email address as your randomly generated password will be sent to that address.',
+'Confirm email' => 'Confirm email address',
+
+);
diff --git a/lang/English/search.php b/lang/English/search.php
new file mode 100644
index 0000000..d6a5081
--- /dev/null
+++ b/lang/English/search.php
@@ -0,0 +1,49 @@
+ 'User search',
+'No search permission' => 'You do not have permission to use the search feature.',
+'Search flood' => 'At least %s seconds have to pass between searches. Please wait a while and try searching again.',
+'Search' => 'Search',
+'Search criteria legend' => 'Enter your search criteria',
+'Search info' => 'To search by keyword, enter a term or terms to search for. Separate terms with spaces. Use AND, OR and NOT to refine your search. To search by author enter the username of the author whose posts you wish to search for. Use wildcard character * for partial matches.',
+'Keyword search' => 'Keyword search',
+'Author search' => 'Author search',
+'Search in legend' => 'Select where to search',
+'Search in info' => 'Choose in which forum you would like to search and if you want to search in topic subjects, message text or both.',
+'Forum search' => 'Forum',
+'All forums' => 'All forums',
+'Search in' => 'Search in',
+'Message and subject' => 'Message text and topic subject',
+'Message only' => 'Message text only',
+'Topic only' => 'Topic subject only',
+'Sort by' => 'Sort by',
+'Sort order' => 'Sort order',
+'Search results legend' => 'Select how to view search results',
+'Search results info' => 'You can choose how you wish to sort and show your results.',
+'Sort by post time' => 'Post time',
+'Sort by author' => 'Author',
+'Sort by subject' => 'Subject',
+'Sort by forum' => 'Forum',
+'Ascending' => 'Ascending',
+'Descending' => 'Descending',
+'Show as' => 'Show results as',
+'Show as topics' => 'Topics',
+'Show as posts' => 'Posts',
+
+// Results
+'Search results' => 'Search results',
+'No terms' => 'You have to enter at least one keyword and/or an author to search for.',
+'No hits' => 'Your search returned no hits.',
+'No user posts' => 'There are no posts by this user in this forum.',
+'No subscriptions' => 'You are currently not subscribed to any topics.',
+'No new posts' => 'There are no topics with new posts since your last visit.',
+'No recent posts' => 'No new posts have been made within the last 24 hours.',
+'No unanswered' => 'There are no unanswered posts in this forum.',
+'Go to post' => 'Go to post',
+'Go to topic' => 'Go to topic'
+
+);
diff --git a/lang/English/stopwords.txt b/lang/English/stopwords.txt
new file mode 100644
index 0000000..907a260
--- /dev/null
+++ b/lang/English/stopwords.txt
@@ -0,0 +1,175 @@
+about
+after
+ago
+all
+almost
+along
+also
+any
+anybody
+anywhere
+are
+arent
+aren't
+around
+ask
+been
+before
+being
+between
+but
+came
+can
+cant
+can't
+come
+could
+couldnt
+couldn't
+did
+didnt
+didn't
+does
+doesnt
+doesn't
+dont
+don't
+each
+either
+else
+even
+every
+everybody
+everyone
+find
+for
+from
+get
+going
+gone
+got
+had
+has
+have
+havent
+haven't
+having
+her
+here
+hers
+him
+his
+how
+ill
+i'll
+i'm
+into
+isnt
+isn't
+itll
+it'll
+its
+it's
+ive
+i've
+just
+know
+less
+like
+make
+many
+may
+more
+most
+much
+must
+near
+never
+none
+nothing
+now
+off
+often
+once
+one
+only
+other
+our
+ours
+our's
+out
+over
+please
+rather
+really
+said
+see
+she
+should
+small
+some
+something
+sometime
+somewhere
+take
+than
+thank
+thanks
+that
+thats
+that's
+the
+their
+theirs
+them
+then
+there
+these
+they
+thing
+think
+this
+those
+though
+through
+thus
+too
+true
+two
+under
+until
+upon
+use
+very
+want
+was
+way
+well
+were
+what
+when
+where
+which
+who
+whom
+whose
+why
+will
+with
+within
+without
+would
+yes
+yet
+you
+your
+youre
+you're
+yours
+http
+https
+ftp
+www
+com
+net
+org
diff --git a/lang/English/topic.php b/lang/English/topic.php
new file mode 100644
index 0000000..1f74dda
--- /dev/null
+++ b/lang/English/topic.php
@@ -0,0 +1,31 @@
+ 'Post reply',
+'Topic closed' => 'Topic closed',
+'From' => 'From:', // User location
+'IP address logged' => 'IP address logged',
+'Note' => 'Note:', // Admin note
+'Posts' => 'Posts:',
+'Registered' => 'Registered:',
+'Replies' => 'Replies:',
+'Website' => 'Website',
+'Guest' => 'Guest',
+'Online' => 'Online',
+'Offline' => 'Offline',
+'Last edit' => 'Last edited by',
+'Report' => 'Report',
+'Delete' => 'Delete',
+'Edit' => 'Edit',
+'Quote' => 'Quote',
+'Is subscribed' => 'You are currently subscribed to this topic',
+'Unsubscribe' => 'Unsubscribe',
+'Subscribe' => 'Subscribe to this topic',
+'Quick post' => 'Quick post',
+'Mod controls' => 'Moderator controls',
+'New icon' => 'New post',
+'Re' => 'Re:'
+
+);
diff --git a/lang/English/userlist.php b/lang/English/userlist.php
new file mode 100644
index 0000000..0853d25
--- /dev/null
+++ b/lang/English/userlist.php
@@ -0,0 +1,13 @@
+ 'Find and sort users',
+'User search info' => 'Enter a username to search for and/or a user group to filter by. The username field can be left blank. Use the wildcard character * for partial matches.',
+'User sort info' => 'Sort users by name, date registered or number of posts and in ascending/descending order.',
+'User group' => 'User group',
+'No of posts' => 'Number of posts',
+'All users' => 'All'
+
+);
diff --git a/lang/index.html b/lang/index.html
new file mode 100644
index 0000000..89337b2
--- /dev/null
+++ b/lang/index.html
@@ -0,0 +1 @@
+..
diff --git a/login.php b/login.php
new file mode 100644
index 0000000..0f899c4
--- /dev/null
+++ b/login.php
@@ -0,0 +1,263 @@
+escape($form_username).'\'' : 'LOWER(username)=LOWER(\''.$db->escape($form_username).'\')';
+
+ $result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE '.$username_sql) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+ $cur_user = $db->fetch_assoc($result);
+
+ $authorized = false;
+
+ if (!empty($cur_user['password']))
+ {
+ $form_password_hash = pun_hash($form_password); // Will result in a SHA-1 hash
+
+ // If there is a salt in the database we have upgraded from 1.3-legacy though havent yet logged in
+ if (!empty($cur_user['salt']))
+ {
+ if (sha1($cur_user['salt'].sha1($form_password)) == $cur_user['password']) // 1.3 used sha1(salt.sha1(pass))
+ {
+ $authorized = true;
+
+ $db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\', salt=NULL WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
+ }
+ }
+ // If the length isn't 40 then the password isn't using sha1, so it must be md5 from 1.2
+ else if (strlen($cur_user['password']) != 40)
+ {
+ if (md5($form_password) == $cur_user['password'])
+ {
+ $authorized = true;
+
+ $db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\' WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error());
+ }
+ }
+ // Otherwise we should have a normal sha1 password
+ else
+ $authorized = ($cur_user['password'] == $form_password_hash);
+ }
+
+ if (!$authorized)
+ message($lang_login['Wrong user/pass'].' '.$lang_login['Forgotten pass'].'');
+
+ // Update the status if this is the first time the user logged in
+ if ($cur_user['group_id'] == PUN_UNVERIFIED)
+ $db->query('UPDATE '.$db->prefix.'users SET group_id='.$pun_config['o_default_user_group'].' WHERE id='.$cur_user['id']) or error('Unable to update user status', __FILE__, __LINE__, $db->error());
+
+ // Remove this users guest entry from the online list
+ $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape(get_remote_address()).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+
+ $expire = ($save_pass == '1') ? time() + 1209600 : time() + $pun_config['o_timeout_visit'];
+ pun_setcookie($cur_user['id'], $form_password_hash, $expire);
+
+ // Reset tracked topics
+ set_tracked_topics(null);
+
+ redirect(htmlspecialchars($_POST['redirect_url']), $lang_login['Login redirect']);
+}
+
+
+else if ($action == 'out')
+{
+ if ($pun_user['is_guest'] || !isset($_GET['id']) || $_GET['id'] != $pun_user['id'] || !isset($_GET['csrf_token']) || $_GET['csrf_token'] != pun_hash($pun_user['id'].pun_hash(get_remote_address())))
+ {
+ header('Location: index.php');
+ exit;
+ }
+
+ // Remove user from "users online" list
+ $db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$pun_user['id']) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
+
+ // Update last_visit (make sure there's something to update it with)
+ if (isset($pun_user['logged']))
+ $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
+
+ pun_setcookie(1, md5(uniqid(rand(), true)), time() + 31536000);
+
+ redirect('index.php', $lang_login['Logout redirect']);
+}
+
+
+else if ($action == 'forget' || $action == 'forget_2')
+{
+ if (!$pun_user['is_guest'])
+ header('Location: index.php');
+
+ if (isset($_POST['form_sent']))
+ {
+ // Start with a clean slate
+ $errors = array();
+
+ require PUN_ROOT.'include/email.php';
+
+ // Validate the email address
+ $email = strtolower(trim($_POST['req_email']));
+ if (!is_valid_email($email))
+ $errors[] = $lang_common['Invalid email'];
+
+ // Did everything go according to plan?
+ if (empty($errors))
+ {
+ $result = $db->query('SELECT id, username, last_email_sent FROM '.$db->prefix.'users WHERE email=\''.$db->escape($email).'\'') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result))
+ {
+ // Load the "activate password" template
+ $mail_tpl = trim(file_get_contents(PUN_ROOT.'lang/'.$pun_user['language'].'/mail_templates/activate_password.tpl'));
+
+ // The first row contains the subject
+ $first_crlf = strpos($mail_tpl, "\n");
+ $mail_subject = trim(substr($mail_tpl, 8, $first_crlf-8));
+ $mail_message = trim(substr($mail_tpl, $first_crlf));
+
+ // Do the generic replacements first (they apply to all emails sent out here)
+ $mail_message = str_replace('', $pun_config['o_base_url'].'/', $mail_message);
+ $mail_message = str_replace('', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message);
+
+ // Loop through users we found
+ while ($cur_hit = $db->fetch_assoc($result))
+ {
+ if ($cur_hit['last_email_sent'] != '' && (time() - $cur_hit['last_email_sent']) < 3600 && (time() - $cur_hit['last_email_sent']) >= 0)
+ message($lang_login['Email flood'], true);
+
+ // Generate a new password and a new password activation code
+ $new_password = random_pass(8);
+ $new_password_key = random_pass(8);
+
+ $db->query('UPDATE '.$db->prefix.'users SET activate_string=\''.pun_hash($new_password).'\', activate_key=\''.$new_password_key.'\', last_email_sent = '.time().' WHERE id='.$cur_hit['id']) or error('Unable to update activation data', __FILE__, __LINE__, $db->error());
+
+ // Do the user specific replacements to the template
+ $cur_mail_message = str_replace('', $cur_hit['username'], $mail_message);
+ $cur_mail_message = str_replace('', $pun_config['o_base_url'].'/profile.php?id='.$cur_hit['id'].'&action=change_pass&key='.$new_password_key, $cur_mail_message);
+ $cur_mail_message = str_replace('', $new_password, $cur_mail_message);
+
+ pun_mail($email, $mail_subject, $cur_mail_message);
+ }
+
+ message($lang_login['Forget mail'].' '.$pun_config['o_admin_email'].'.', true);
+ }
+ else
+ $errors[] = $lang_login['No email match'].' '.htmlspecialchars($email).'.';
+ }
+ }
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_login['Request pass']);
+ $required_fields = array('req_email' => $lang_common['Email']);
+ $focus_element = array('request_pass', 'req_email');
+ define ('PUN_ACTIVE_PAGE', 'login');
+ require PUN_ROOT.'header.php';
+
+// If there are errors, we display them
+if (!empty($errors))
+{
+
+?>
+
+query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user last visit data', __FILE__, __LINE__, $db->error());
+
+ // Reset tracked topics
+ set_tracked_topics(null);
+
+ redirect('index.php', $lang_misc['Mark read redirect']);
+}
+
+
+// Mark the topics/posts in a forum as read?
+else if ($action == 'markforumread')
+{
+ if ($pun_user['is_guest'])
+ message($lang_common['No permission']);
+
+ $fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
+ if ($fid < 1)
+ message($lang_common['Bad request']);
+
+ $tracked_topics = get_tracked_topics();
+ $tracked_topics['forums'][$fid] = time();
+ set_tracked_topics($tracked_topics);
+
+ redirect('viewforum.php?id='.$fid, $lang_misc['Mark forum read redirect']);
+}
+
+
+else if (isset($_GET['email']))
+{
+ if ($pun_user['is_guest'] || $pun_user['g_send_email'] == '0')
+ message($lang_common['No permission']);
+
+ $recipient_id = intval($_GET['email']);
+ if ($recipient_id < 2)
+ message($lang_common['Bad request']);
+
+ $result = $db->query('SELECT username, email, email_setting FROM '.$db->prefix.'users WHERE id='.$recipient_id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ list($recipient, $recipient_email, $email_setting) = $db->fetch_row($result);
+
+ if ($email_setting == 2 && !$pun_user['is_admmod'])
+ message($lang_misc['Form email disabled']);
+
+
+ if (isset($_POST['form_sent']))
+ {
+ // Clean up message and subject from POST
+ $subject = pun_trim($_POST['req_subject']);
+ $message = pun_trim($_POST['req_message']);
+
+ if ($subject == '')
+ message($lang_misc['No email subject']);
+ else if ($message == '')
+ message($lang_misc['No email message']);
+ else if (pun_strlen($message) > PUN_MAX_POSTSIZE)
+ message($lang_misc['Too long email message']);
+
+ if ($pun_user['last_email_sent'] != '' && (time() - $pun_user['last_email_sent']) < $pun_user['g_email_flood'] && (time() - $pun_user['last_email_sent']) >= 0)
+ message(sprintf($lang_misc['Email flood'], $pun_user['g_email_flood']));
+
+ // Load the "form email" template
+ $mail_tpl = trim(file_get_contents(PUN_ROOT.'lang/'.$pun_user['language'].'/mail_templates/form_email.tpl'));
+
+ // The first row contains the subject
+ $first_crlf = strpos($mail_tpl, "\n");
+ $mail_subject = pun_trim(substr($mail_tpl, 8, $first_crlf-8));
+ $mail_message = pun_trim(substr($mail_tpl, $first_crlf));
+
+ $mail_subject = str_replace('', $subject, $mail_subject);
+ $mail_message = str_replace('', $pun_user['username'], $mail_message);
+ $mail_message = str_replace('', $pun_config['o_board_title'], $mail_message);
+ $mail_message = str_replace('', $message, $mail_message);
+ $mail_message = str_replace('', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message);
+
+ require_once PUN_ROOT.'include/email.php';
+
+ pun_mail($recipient_email, $mail_subject, $mail_message, $pun_user['email'], $pun_user['username']);
+
+ $db->query('UPDATE '.$db->prefix.'users SET last_email_sent='.time().' WHERE id='.$pun_user['id']) or error('Unable to update user', __FILE__, __LINE__, $db->error());
+
+ redirect(htmlspecialchars($_POST['redirect_url']), $lang_misc['Email sent redirect']);
+ }
+
+
+ // Try to determine if the data in HTTP_REFERER is valid (if not, we redirect to the users profile after the email is sent)
+ $redirect_url = (isset($_SERVER['HTTP_REFERER']) && preg_match('#^'.preg_quote($pun_config['o_base_url']).'/(.*?)\.php#i', $_SERVER['HTTP_REFERER'])) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : 'index.php';
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Send email to'].' '.pun_htmlspecialchars($recipient));
+ $required_fields = array('req_subject' => $lang_misc['Email subject'], 'req_message' => $lang_misc['Email message']);
+ $focus_element = array('email', 'req_subject');
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
+
+= 0)
+ message(sprintf($lang_misc['Report flood'], $pun_user['g_email_flood']));
+
+ // Get the topic ID
+ $result = $db->query('SELECT topic_id FROM '.$db->prefix.'posts WHERE id='.$post_id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $topic_id = $db->result($result);
+
+ // Get the subject and forum ID
+ $result = $db->query('SELECT subject, forum_id FROM '.$db->prefix.'topics WHERE id='.$topic_id) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ list($subject, $forum_id) = $db->fetch_row($result);
+
+ // Should we use the internal report handling?
+ if ($pun_config['o_report_method'] == '0' || $pun_config['o_report_method'] == '2')
+ $db->query('INSERT INTO '.$db->prefix.'reports (post_id, topic_id, forum_id, reported_by, created, message) VALUES('.$post_id.', '.$topic_id.', '.$forum_id.', '.$pun_user['id'].', '.time().', \''.$db->escape($reason).'\')' ) or error('Unable to create report', __FILE__, __LINE__, $db->error());
+
+ // Should we email the report?
+ if ($pun_config['o_report_method'] == '1' || $pun_config['o_report_method'] == '2')
+ {
+ // We send it to the complete mailing-list in one swoop
+ if ($pun_config['o_mailing_list'] != '')
+ {
+ $mail_subject = sprintf($lang_common['Report notification'], $forum_id, $subject);
+ $mail_message = sprintf($lang_common['Report message 1'], $pun_user['username'], $pun_config['o_base_url'].'/viewtopic.php?pid='.$post_id.'#p'.$post_id)."\n";
+ $mail_message .= sprintf($lang_common['Report message 2'], $reason)."\n";
+ $mail_message .= "\n".'--'."\n".$lang_common['Email signature'];
+
+ require PUN_ROOT.'include/email.php';
+
+ pun_mail($pun_config['o_mailing_list'], $mail_subject, $mail_message);
+ }
+ }
+
+ $db->query('UPDATE '.$db->prefix.'users SET last_email_sent='.time().' WHERE id='.$pun_user['id']) or error('Unable to update user', __FILE__, __LINE__, $db->error());
+
+ redirect('viewtopic.php?pid='.$post_id.'#p'.$post_id, $lang_misc['Report redirect']);
+ }
+
+ // Fetch some info about the post, the topic and the forum
+ $result = $db->query('SELECT f.id AS fid, f.forum_name, t.id AS tid, t.subject FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'topics AS t ON t.id=p.topic_id INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND p.id='.$post_id) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $cur_post = $db->fetch_assoc($result);
+
+ if ($pun_config['o_censoring'] == '1')
+ $cur_post['subject'] = censor_words($cur_post['subject']);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Report post']);
+ $required_fields = array('req_reason' => $lang_misc['Reason']);
+ $focus_element = array('report', 'req_reason');
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
»
+
»
+
»
+
+
+
+
+
+
+
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$topic_id.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'subscriptions WHERE user_id='.$pun_user['id'].' AND topic_id='.$topic_id) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ message($lang_misc['Already subscribed']);
+
+ $db->query('INSERT INTO '.$db->prefix.'subscriptions (user_id, topic_id) VALUES('.$pun_user['id'].' ,'.$topic_id.')') or error('Unable to add subscription', __FILE__, __LINE__, $db->error());
+
+ redirect('viewtopic.php?id='.$topic_id, $lang_misc['Subscribe redirect']);
+}
+
+
+else if (isset($_GET['unsubscribe']))
+{
+ if ($pun_user['is_guest'] || $pun_config['o_subscriptions'] != '1')
+ message($lang_common['No permission']);
+
+ $topic_id = intval($_GET['unsubscribe']);
+ if ($topic_id < 1)
+ message($lang_common['Bad request']);
+
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'subscriptions WHERE user_id='.$pun_user['id'].' AND topic_id='.$topic_id) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_misc['Not subscribed']);
+
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE user_id='.$pun_user['id'].' AND topic_id='.$topic_id) or error('Unable to remove subscription', __FILE__, __LINE__, $db->error());
+
+ redirect('viewtopic.php?id='.$topic_id, $lang_misc['Unsubscribe redirect']);
+}
+
+
+else
+ message($lang_common['Bad request']);
diff --git a/moderate.php b/moderate.php
new file mode 100644
index 0000000..82f5ae1
--- /dev/null
+++ b/moderate.php
@@ -0,0 +1,915 @@
+query('SELECT poster_ip FROM '.$db->prefix.'posts WHERE id='.$get_host) or error('Unable to fetch post IP address', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $ip = $db->result($result);
+ }
+
+ // Load the misc.php language file
+ require PUN_ROOT.'lang/'.$pun_user['language'].'/misc.php';
+
+ message(sprintf($lang_misc['Host info 1'], $ip).' '.sprintf($lang_misc['Host info 2'], @gethostbyaddr($ip)).'
'.$lang_misc['Show more users'].'');
+}
+
+
+// All other functions require moderator/admin access
+$fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
+if ($fid < 1)
+ message($lang_common['Bad request']);
+
+$result = $db->query('SELECT moderators FROM '.$db->prefix.'forums WHERE id='.$fid) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+
+$moderators = $db->result($result);
+$mods_array = ($moderators != '') ? unserialize($moderators) : array();
+
+if ($pun_user['g_id'] != PUN_ADMIN && ($pun_user['g_moderator'] == '0' || !array_key_exists($pun_user['username'], $mods_array)))
+ message($lang_common['No permission']);
+
+// Get topic/forum tracking data
+if (!$pun_user['is_guest'])
+ $tracked_topics = get_tracked_topics();
+
+// Load the misc.php language file
+require PUN_ROOT.'lang/'.$pun_user['language'].'/misc.php';
+
+
+// All other topic moderation features require a topic ID in GET
+if (isset($_GET['tid']))
+{
+ $tid = intval($_GET['tid']);
+ if ($tid < 1)
+ message($lang_common['Bad request']);
+
+ // Fetch some info about the topic
+ $result = $db->query('SELECT t.subject, t.num_replies, t.first_post_id, f.id AS forum_id, forum_name FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fid.' AND t.id='.$tid.' AND t.moved_to IS NULL') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+ if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+ $cur_topic = $db->fetch_assoc($result);
+
+ // Delete one or more posts
+ if (isset($_POST['delete_posts']) || isset($_POST['delete_posts_comply']))
+ {
+ $posts = isset($_POST['posts']) ? $_POST['posts'] : array();
+ if (empty($posts))
+ message($lang_misc['No posts selected']);
+
+ if (isset($_POST['delete_posts_comply']))
+ {
+ confirm_referrer('moderate.php');
+
+ if (@preg_match('/[^0-9,]/', $posts))
+ message($lang_common['Bad request']);
+
+ // Verify that the post IDs are valid
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE id IN('.$posts.') AND topic_id='.$tid) or error('Unable to check posts', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result) != substr_count($posts, ',') + 1)
+ message($lang_common['Bad request']);
+
+ // Delete the posts
+ $db->query('DELETE FROM '.$db->prefix.'posts WHERE id IN('.$posts.')') or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
+
+ require PUN_ROOT.'include/search_idx.php';
+ strip_search_index($posts);
+
+ // Get last_post, last_post_id, and last_poster for the topic after deletion
+ $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$tid.' ORDER BY id DESC LIMIT 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $last_post = $db->fetch_assoc($result);
+
+ // How many posts did we just delete?
+ $num_posts_deleted = substr_count($posts, ',') + 1;
+
+ // Update the topic
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$last_post['posted'].', last_post_id='.$last_post['id'].', last_poster=\''.$db->escape($last_post['poster']).'\', num_replies=num_replies-'.$num_posts_deleted.' WHERE id='.$tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ update_forum($fid);
+
+ redirect('viewtopic.php?id='.$tid, $lang_misc['Delete posts redirect']);
+ }
+
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Moderate']);
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'posts WHERE id IN('.$posts.') AND topic_id='.$tid) or error('Unable to check posts', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result) != $num_posts_splitted)
+ message($lang_common['Bad request']);
+
+ // Load the post.php language file
+ require PUN_ROOT.'lang/'.$pun_user['language'].'/post.php';
+
+ // Check subject
+ $new_subject = isset($_POST['new_subject']) ? pun_trim($_POST['new_subject']) : '';
+
+ if ($new_subject == '')
+ message($lang_post['No subject']);
+ else if (pun_strlen($new_subject) > 70)
+ message($lang_post['Too long subject']);
+
+ // Get data from the new first post
+ $result = $db->query('SELECT p.id, p.poster, p.posted FROM '.$db->prefix.'posts AS p WHERE id IN('.$posts.') ORDER BY p.id ASC LIMIT 1') or error('Unable to get first post', __FILE__, __LINE__, $db->error());
+ $first_post_data = $db->fetch_assoc($result);
+
+ // Create the new topic
+ $db->query('INSERT INTO '.$db->prefix.'topics (poster, subject, posted, first_post_id, forum_id) VALUES (\''.$db->escape($first_post_data['poster']).'\', \''.$db->escape($new_subject).'\', '.$first_post_data['posted'].', '.$first_post_data['id'].', '.$fid.')') or error('Unable to create new topic', __FILE__, __LINE__, $db->error());
+ $new_tid = $db->insert_id();
+
+ // Move the posts to the new topic
+ $db->query('UPDATE '.$db->prefix.'posts SET topic_id='.$new_tid.' WHERE id IN('.$posts.')') or error('Unable to move posts into new topic', __FILE__, __LINE__, $db->error());
+
+ // Get last_post, last_post_id, and last_poster from the topic and update it
+ $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$tid.' ORDER BY id DESC LIMIT 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $last_post_data = $db->fetch_assoc($result);
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$last_post_data['posted'].', last_post_id='.$last_post_data['id'].', last_poster=\''.$db->escape($last_post_data['poster']).'\', num_replies=num_replies-'.$num_posts_splitted.' WHERE id='.$tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ // Get last_post, last_post_id, and last_poster from the new topic and update it
+ $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$new_tid.' ORDER BY id DESC LIMIT 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $last_post_data = $db->fetch_assoc($result);
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$last_post_data['posted'].', last_post_id='.$last_post_data['id'].', last_poster=\''.$db->escape($last_post_data['poster']).'\', num_replies='.($num_posts_splitted-1).' WHERE id='.$new_tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ update_forum($fid);
+
+ redirect('viewtopic.php?id='.$new_tid, $lang_misc['Split posts redirect']);
+ }
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Moderate']);
+ $focus_element = array('subject','new_subject');
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.implode(',',$topics).') AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result) != count($topics))
+ message($lang_common['Bad request']);
+
+ // Delete any redirect topics if there are any (only if we moved/copied the topic back to where it was once moved from)
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE forum_id='.$move_to_forum.' AND moved_to IN('.implode(',',$topics).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
+
+ // Move the topic(s)
+ $db->query('UPDATE '.$db->prefix.'topics SET forum_id='.$move_to_forum.' WHERE id IN('.implode(',',$topics).')') or error('Unable to move topics', __FILE__, __LINE__, $db->error());
+
+ // Should we create redirect topics?
+ if (isset($_POST['with_redirect']))
+ {
+ foreach ($topics as $cur_topic)
+ {
+ // Fetch info for the redirect topic
+ $result = $db->query('SELECT poster, subject, posted, last_post FROM '.$db->prefix.'topics WHERE id='.$cur_topic) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
+ $moved_to = $db->fetch_assoc($result);
+
+ // Create the redirect topic
+ $db->query('INSERT INTO '.$db->prefix.'topics (poster, subject, posted, last_post, moved_to, forum_id) VALUES(\''.$db->escape($moved_to['poster']).'\', \''.$db->escape($moved_to['subject']).'\', '.$moved_to['posted'].', '.$moved_to['last_post'].', '.$cur_topic.', '.$fid.')') or error('Unable to create redirect topic', __FILE__, __LINE__, $db->error());
+ }
+ }
+
+ update_forum($fid); // Update the forum FROM which the topic was moved
+ update_forum($move_to_forum); // Update the forum TO which the topic was moved
+
+ $redirect_msg = (count($topics) > 1) ? $lang_misc['Move topics redirect'] : $lang_misc['Move topic redirect'];
+ redirect('viewforum.php?id='.$move_to_forum, $redirect_msg);
+ }
+
+ if (isset($_POST['move_topics']))
+ {
+ $topics = isset($_POST['topics']) ? $_POST['topics'] : array();
+ if (empty($topics))
+ message($lang_misc['No topics selected']);
+
+ $topics = implode(',', array_map('intval', array_keys($topics)));
+ $action = 'multi';
+ }
+ else
+ {
+ $topics = intval($_GET['move_topics']);
+ if ($topics < 1)
+ message($lang_common['Bad request']);
+
+ $action = 'single';
+ }
+
+ $result = $db->query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.redirect_url IS NULL ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result) < 2)
+ message($lang_misc['Nowhere to move']);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Moderate']);
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $topics).') AND moved_to IS NULL AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+ $result = $db->query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $topics).') AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result) != count($topics))
+ message($lang_common['Bad request']);
+
+ // Fetch the topic that we're merging into
+ $result = $db->query('SELECT MIN(t.id) FROM '.$db->prefix.'topics AS t WHERE t.id IN('.implode(',', $topics).')') or error('Unable to get topic', __FILE__, __LINE__, $db->error());
+ $merge_to_tid = $db->result($result);
+
+ // Make any redirect topics point to our new, merged topic
+ $query = 'UPDATE '.$db->prefix.'topics SET moved_to='.$merge_to_tid.' WHERE moved_to IN('.implode(',', $topics).')';
+
+ // Should we create redirect topics?
+ if (isset($_POST['with_redirect']))
+ $query .= ' OR (id IN('.implode(',', $topics).') AND id != '.$merge_to_tid.')';
+
+ $db->query($query) or error('Unable to make redirection topics', __FILE__, __LINE__, $db->error());
+
+ // Merge the posts into the topic
+ $db->query('UPDATE '.$db->prefix.'posts SET topic_id='.$merge_to_tid.' WHERE topic_id IN('.implode(',', $topics).')') or error('Unable to merge the posts into the topic', __FILE__, __LINE__, $db->error());
+
+ // Delete any subscriptions
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id IN('.implode(',', $topics).') AND topic_id != '.$merge_to_tid) or error('Unable to delete subscriptions', __FILE__, __LINE__, $db->error());
+
+ // Without redirection the old topics are removed
+ if (!isset($_POST['with_redirect']))
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $topics).') AND id != '.$merge_to_tid) or error('Unable to delete old topics', __FILE__, __LINE__, $db->error());
+
+ // Count number of replies in the topic
+ $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$merge_to_tid) or error('Unable to fetch post count for topic', __FILE__, __LINE__, $db->error());
+ $num_replies = $db->result($result, 0) - 1;
+
+ // Get last_post, last_post_id and last_poster
+ $result = $db->query('SELECT posted, id, poster FROM '.$db->prefix.'posts WHERE topic_id='.$merge_to_tid.' ORDER BY id DESC LIMIT 1') or error('Unable to get last post info', __FILE__, __LINE__, $db->error());
+ list($last_post, $last_post_id, $last_poster) = $db->fetch_row($result);
+
+ // Update topic
+ $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$merge_to_tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ // Update the forum FROM which the topic was moved and redirect
+ update_forum($fid);
+ redirect('viewforum.php?id='.$fid, $lang_misc['Merge topics redirect']);
+ }
+
+ $topics = isset($_POST['topics']) ? $_POST['topics'] : array();
+ if (count($topics) < 2)
+ message($lang_misc['Not enough topics selected']);
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Moderate']);
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
+
+query('SELECT 1 FROM '.$db->prefix.'topics WHERE id IN('.$topics.') AND forum_id='.$fid) or error('Unable to check topics', __FILE__, __LINE__, $db->error());
+
+ if ($db->num_rows($result) != substr_count($topics, ',') + 1)
+ message($lang_common['Bad request']);
+
+ // Delete the topics and any redirect topics
+ $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.$topics.') OR moved_to IN('.$topics.')') or error('Unable to delete topic', __FILE__, __LINE__, $db->error());
+
+ // Delete any subscriptions
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id IN('.$topics.')') or error('Unable to delete subscriptions', __FILE__, __LINE__, $db->error());
+
+ // Create a list of the post IDs in this topic and then strip the search index
+ $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id IN('.$topics.')') or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
+
+ $post_ids = '';
+ while ($row = $db->fetch_row($result))
+ $post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
+
+ // We have to check that we actually have a list of post IDs since we could be deleting just a redirect topic
+ if ($post_ids != '')
+ strip_search_index($post_ids);
+
+ // Delete posts
+ $db->query('DELETE FROM '.$db->prefix.'posts WHERE topic_id IN('.$topics.')') or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
+
+ update_forum($fid);
+
+ redirect('viewforum.php?id='.$fid, $lang_misc['Delete topics redirect']);
+ }
+
+
+ $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_misc['Moderate']);
+ define('PUN_ACTIVE_PAGE', 'index');
+ require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
+
+query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id IN('.implode(',', $topics).') AND forum_id='.$fid) or error('Unable to close topics', __FILE__, __LINE__, $db->error());
+
+ $redirect_msg = ($action) ? $lang_misc['Close topics redirect'] : $lang_misc['Open topics redirect'];
+ redirect('moderate.php?fid='.$fid, $redirect_msg);
+ }
+ // Or just one in $_GET
+ else
+ {
+ confirm_referrer('viewtopic.php');
+
+ $topic_id = ($action) ? intval($_GET['close']) : intval($_GET['open']);
+ if ($topic_id < 1)
+ message($lang_common['Bad request']);
+
+ $db->query('UPDATE '.$db->prefix.'topics SET closed='.$action.' WHERE id='.$topic_id.' AND forum_id='.$fid) or error('Unable to close topic', __FILE__, __LINE__, $db->error());
+
+ $redirect_msg = ($action) ? $lang_misc['Close topic redirect'] : $lang_misc['Open topic redirect'];
+ redirect('viewtopic.php?id='.$topic_id, $redirect_msg);
+ }
+}
+
+
+// Stick a topic
+else if (isset($_GET['stick']))
+{
+ confirm_referrer('viewtopic.php');
+
+ $stick = intval($_GET['stick']);
+ if ($stick < 1)
+ message($lang_common['Bad request']);
+
+ $db->query('UPDATE '.$db->prefix.'topics SET sticky=\'1\' WHERE id='.$stick.' AND forum_id='.$fid) or error('Unable to stick topic', __FILE__, __LINE__, $db->error());
+
+ redirect('viewtopic.php?id='.$stick, $lang_misc['Stick topic redirect']);
+}
+
+
+// Unstick a topic
+else if (isset($_GET['unstick']))
+{
+ confirm_referrer('viewtopic.php');
+
+ $unstick = intval($_GET['unstick']);
+ if ($unstick < 1)
+ message($lang_common['Bad request']);
+
+ $db->query('UPDATE '.$db->prefix.'topics SET sticky=\'0\' WHERE id='.$unstick.' AND forum_id='.$fid) or error('Unable to unstick topic', __FILE__, __LINE__, $db->error());
+
+ redirect('viewtopic.php?id='.$unstick, $lang_misc['Unstick topic redirect']);
+}
+
+
+// No specific forum moderation action was specified in the query string, so we'll display the moderator forum
+
+// Load the viewforum.php language file
+require PUN_ROOT.'lang/'.$pun_user['language'].'/forum.php';
+
+// Fetch some info about the forum
+$result = $db->query('SELECT f.forum_name, f.redirect_url, f.num_topics, f.sort_by FROM '.$db->prefix.'forums AS f LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fid) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+$cur_forum = $db->fetch_assoc($result);
+
+// Is this a redirect forum? In that case, abort!
+if ($cur_forum['redirect_url'] != '')
+ message($lang_common['Bad request']);
+
+// Determine the topic offset (based on $_GET['p'])
+$num_pages = ceil($cur_forum['num_topics'] / $pun_user['disp_topics']);
+
+$p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
+$start_from = $pun_user['disp_topics'] * ($p - 1);
+
+// Generate paging links
+$paging_links = ''.$lang_common['Pages'].' '.paginate($num_pages, $p, 'moderate.php?fid='.$fid);
+
+$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), pun_htmlspecialchars($cur_forum['forum_name']));
+define('PUN_ACTIVE_PAGE', 'index');
+require PUN_ROOT.'header.php';
+
+?>
+
+
+
+
+
»
+
»
+
+
+
+
+
+
+
+
+
+ tags and the target
+## URL for the redirect() function must be set to the value of
+## $_SERVER['REQUEST_URI']. This URL can however be extended to
+## include extra variables (like the addition of &foo=bar in
+## the form of this example plugin).
+##
+## 4. If your plugin is for administrators only, the filename must
+## have the prefix "AP_". If it is for both administrators and
+## moderators, use the prefix "AMP_". This example plugin has the
+## prefix "AMP_" and is therefore available for both admins and
+## moderators in the navigation menu.
+##
+## 5. Use _ instead of spaces in the file name.
+##
+## 6. Since plugin scripts are included from the FluxBB script
+## admin_loader.php, you have access to all FluxBB functions and
+## global variables (e.g. $db, $pun_config, $pun_user etc).
+##
+## 7. Do your best to keep the look and feel of your plugins' user
+## interface similar to the rest of the admin scripts. Feel free to
+## borrow markup and code from the admin scripts to use in your
+## plugins. If you create your own styles they need to be added to
+## the "base_admin" style sheet.
+##
+## 8. Plugins must be released under the GNU General Public License or
+## a GPL compatible license. Copy the GPL preamble at the top of
+## this file into your plugin script and alter the copyright notice
+## to refrect the author of the plugin (i.e. you).
+##
+##
+
+
+// Make sure no one attempts to run this script "directly"
+if (!defined('PUN'))
+ exit;
+
+// Load the admin_bans.php language file
+require PUN_ROOT.'lang/'.$admin_language.'/admin_plugin_example.php';
+
+// Tell admin_loader.php that this is indeed a plugin and that it is loaded
+define('PUN_PLUGIN_LOADED', 1);
+
+//
+// The rest is up to you!
+//
+
+// If the "Show text" button was clicked
+if (isset($_POST['show_text']))
+{
+ // Make sure something was entered
+ if (trim($_POST['text_to_show']) == '')
+ message($lang_admin_plugin_example['No text']);
+
+ // Display the admin navigation menu
+ generate_admin_menu($plugin);
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+..
diff --git a/post.php b/post.php
new file mode 100644
index 0000000..b255172
--- /dev/null
+++ b/post.php
@@ -0,0 +1,616 @@
+ 0 && $fid > 0)
+ message($lang_common['Bad request']);
+
+// Fetch some info about the topic and/or the forum
+if ($tid)
+ $result = $db->query('SELECT f.id, f.forum_name, f.moderators, f.redirect_url, fp.post_replies, fp.post_topics, t.subject, t.closed, s.user_id AS is_subscribed FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id='.$tid) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+else
+ $result = $db->query('SELECT f.id, f.forum_name, f.moderators, f.redirect_url, fp.post_replies, fp.post_topics FROM '.$db->prefix.'forums AS f LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fid) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
+
+if (!$db->num_rows($result))
+ message($lang_common['Bad request']);
+
+$cur_posting = $db->fetch_assoc($result);
+$is_subscribed = $tid && $cur_posting['is_subscribed'];
+
+// Is someone trying to post into a redirect forum?
+if ($cur_posting['redirect_url'] != '')
+ message($lang_common['Bad request']);
+
+// Sort out who the moderators are and if we are currently a moderator (or an admin)
+$mods_array = ($cur_posting['moderators'] != '') ? unserialize($cur_posting['moderators']) : array();
+$is_admmod = ($pun_user['g_id'] == PUN_ADMIN || ($pun_user['g_moderator'] == '1' && array_key_exists($pun_user['username'], $mods_array))) ? true : false;
+
+if ($pun_config['o_censoring'] == '1')
+ $cur_posting['subject'] = censor_words($cur_posting['subject']);
+
+// Do we have permission to post?
+if ((($tid && (($cur_posting['post_replies'] == '' && $pun_user['g_post_replies'] == '0') || $cur_posting['post_replies'] == '0')) ||
+ ($fid && (($cur_posting['post_topics'] == '' && $pun_user['g_post_topics'] == '0') || $cur_posting['post_topics'] == '0')) ||
+ (isset($cur_posting['closed']) && $cur_posting['closed'] == '1')) &&
+ !$is_admmod)
+ message($lang_common['No permission']);
+
+// Load the post.php language file
+require PUN_ROOT.'lang/'.$pun_user['language'].'/post.php';
+
+// Start with a clean slate
+$errors = array();
+
+
+// Did someone just hit "Submit" or "Preview"?
+if (isset($_POST['form_sent']))
+{
+ // Make sure form_user is correct
+ if (($pun_user['is_guest'] && $_POST['form_user'] != 'Guest') || (!$pun_user['is_guest'] && $_POST['form_user'] != $pun_user['username']))
+ message($lang_common['Bad request']);
+
+ // Flood protection
+ if (!isset($_POST['preview']) && $pun_user['last_post'] != '' && (time() - $pun_user['last_post']) < $pun_user['g_post_flood'])
+ $errors[] = $lang_post['Flood start'].' '.$pun_user['g_post_flood'].' '.$lang_post['flood end'];
+
+ // If it's a new topic
+ if ($fid)
+ {
+ $subject = pun_trim($_POST['req_subject']);
+
+ if ($subject == '')
+ $errors[] = $lang_post['No subject'];
+ else if (pun_strlen($subject) > 70)
+ $errors[] = $lang_post['Too long subject'];
+ else if ($pun_config['p_subject_all_caps'] == '0' && is_all_uppercase($subject) && !$pun_user['is_admmod'])
+ $errors[] = $lang_post['All caps subject'];
+ }
+
+ // If the user is logged in we get the username and email from $pun_user
+ if (!$pun_user['is_guest'])
+ {
+ $username = $pun_user['username'];
+ $email = $pun_user['email'];
+ }
+ // Otherwise it should be in $_POST
+ else
+ {
+ $username = pun_trim($_POST['req_username']);
+ $email = strtolower(trim(($pun_config['p_force_guest_email'] == '1') ? $_POST['req_email'] : $_POST['email']));
+
+ // Load the register.php/profile.php language files
+ require PUN_ROOT.'lang/'.$pun_user['language'].'/prof_reg.php';
+ require PUN_ROOT.'lang/'.$pun_user['language'].'/register.php';
+
+ // It's a guest, so we have to validate the username
+ check_username($username);
+
+ if ($pun_config['p_force_guest_email'] == '1' || $email != '')
+ {
+ require PUN_ROOT.'include/email.php';
+ if (!is_valid_email($email))
+ $errors[] = $lang_common['Invalid email'];
+
+ // Check if it's a banned email address
+ // we should only check guests because members addresses are already verified
+ if ($pun_user['is_guest'] && is_banned_email($email))
+ {
+ if ($pun_config['p_allow_banned_email'] == '0')
+ $errors[] = $lang_prof_reg['Banned email'];
+
+ $banned_email = true; // Used later when we send an alert email
+ }
+ else
+ $banned_email = false;
+ }
+ }
+
+ // Clean up message from POST
+ $message = pun_linebreaks(pun_trim($_POST['req_message']));
+
+ if (pun_strlen($message) > PUN_MAX_POSTSIZE)
+ $errors[] = $lang_post['Too long message'];
+ else if ($pun_config['p_message_all_caps'] == '0' && is_all_uppercase($message) && !$pun_user['is_admmod'])
+ $errors[] = $lang_post['All caps message'];
+
+ // Validate BBCode syntax
+ if ($pun_config['p_message_bbcode'] == '1')
+ {
+ require PUN_ROOT.'include/parser.php';
+ $message = preparse_bbcode($message, $errors);
+ }
+
+ if ($message == '')
+ $errors[] = $lang_post['No message'];
+
+ $hide_smilies = isset($_POST['hide_smilies']) ? '1' : '0';
+ $subscribe = isset($_POST['subscribe']) ? '1' : '0';
+
+ $now = time();
+
+ // Did everything go according to plan?
+ if (empty($errors) && !isset($_POST['preview']))
+ {
+ require PUN_ROOT.'include/search_idx.php';
+
+ // If it's a reply
+ if ($tid)
+ {
+ if (!$pun_user['is_guest'])
+ {
+ $new_tid = $tid;
+
+ // Insert the new post
+ $db->query('INSERT INTO '.$db->prefix.'posts (poster, poster_id, poster_ip, message, hide_smilies, posted, topic_id) VALUES(\''.$db->escape($username).'\', '.$pun_user['id'].', \''.get_remote_address().'\', \''.$db->escape($message).'\', '.$hide_smilies.', '.$now.', '.$tid.')') or error('Unable to create post', __FILE__, __LINE__, $db->error());
+ $new_pid = $db->insert_id();
+
+ // To subscribe or not to subscribe, that ...
+ if ($pun_config['o_subscriptions'] == '1')
+ {
+ if ($subscribe && !$is_subscribed)
+ $db->query('INSERT INTO '.$db->prefix.'subscriptions (user_id, topic_id) VALUES('.$pun_user['id'].' ,'.$tid.')') or error('Unable to add subscription', __FILE__, __LINE__, $db->error());
+ else if (!$subscribe && $is_subscribed)
+ $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE user_id='.$pun_user['id'].' AND topic_id='.$tid) or error('Unable to remove subscription', __FILE__, __LINE__, $db->error());
+ }
+ }
+ else
+ {
+ // It's a guest. Insert the new post
+ $email_sql = ($pun_config['p_force_guest_email'] == '1' || $email != '') ? '\''.$email.'\'' : 'NULL';
+ $db->query('INSERT INTO '.$db->prefix.'posts (poster, poster_ip, poster_email, message, hide_smilies, posted, topic_id) VALUES(\''.$db->escape($username).'\', \''.get_remote_address().'\', '.$email_sql.', \''.$db->escape($message).'\', '.$hide_smilies.', '.$now.', '.$tid.')') or error('Unable to create post', __FILE__, __LINE__, $db->error());
+ $new_pid = $db->insert_id();
+ }
+
+ // Count number of replies in the topic
+ $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$tid) or error('Unable to fetch post count for topic', __FILE__, __LINE__, $db->error());
+ $num_replies = $db->result($result, 0) - 1;
+
+ // Update topic
+ $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.', last_post='.$now.', last_post_id='.$new_pid.', last_poster=\''.$db->escape($username).'\' WHERE id='.$tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ update_search_index('post', $new_pid, $message);
+
+ update_forum($cur_posting['id']);
+
+ // Should we send out notifications?
+ if ($pun_config['o_subscriptions'] == '1')
+ {
+ // Get the post time for the previous post in this topic
+ $result = $db->query('SELECT posted FROM '.$db->prefix.'posts WHERE topic_id='.$tid.' ORDER BY id DESC LIMIT 1, 1') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
+ $previous_post_time = $db->result($result);
+
+ // Get any subscribed users that should be notified (banned users are excluded)
+ $result = $db->query('SELECT u.id, u.email, u.notify_with_post, u.language FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'subscriptions AS s ON u.id=s.user_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id='.$cur_posting['id'].' AND fp.group_id=u.group_id) LEFT JOIN '.$db->prefix.'online AS o ON u.id=o.user_id LEFT JOIN '.$db->prefix.'bans AS b ON u.username=b.username WHERE b.username IS NULL AND COALESCE(o.logged, u.last_visit)>'.$previous_post_time.' AND (fp.read_forum IS NULL OR fp.read_forum=1) AND s.topic_id='.$tid.' AND u.id!='.$pun_user['id']) or error('Unable to fetch subscription info', __FILE__, __LINE__, $db->error());
+ if ($db->num_rows($result))
+ {
+ require_once PUN_ROOT.'include/email.php';
+
+ $notification_emails = array();
+
+ // Loop through subscribed users and send emails
+ while ($cur_subscriber = $db->fetch_assoc($result))
+ {
+ // Is the subscription email for $cur_subscriber['language'] cached or not?
+ if (!isset($notification_emails[$cur_subscriber['language']]))
+ {
+ if (file_exists(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'))
+ {
+ // Load the "new reply" template
+ $mail_tpl = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply.tpl'));
+
+ // Load the "new reply full" template (with post included)
+ $mail_tpl_full = trim(file_get_contents(PUN_ROOT.'lang/'.$cur_subscriber['language'].'/mail_templates/new_reply_full.tpl'));
+
+ // The first row contains the subject (it also starts with "Subject:")
+ $first_crlf = strpos($mail_tpl, "\n");
+ $mail_subject = trim(substr($mail_tpl, 8, $first_crlf-8));
+ $mail_message = trim(substr($mail_tpl, $first_crlf));
+
+ $first_crlf = strpos($mail_tpl_full, "\n");
+ $mail_subject_full = trim(substr($mail_tpl_full, 8, $first_crlf-8));
+ $mail_message_full = trim(substr($mail_tpl_full, $first_crlf));
+
+ $mail_subject = str_replace('', '\''.$cur_posting['subject'].'\'', $mail_subject);
+ $mail_message = str_replace('', '\''.$cur_posting['subject'].'\'', $mail_message);
+ $mail_message = str_replace('', $username, $mail_message);
+ $mail_message = str_replace('', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message);
+ $mail_message = str_replace('', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message);
+ $mail_message = str_replace('', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message);
+
+ $mail_subject_full = str_replace('', '\''.$cur_posting['subject'].'\'', $mail_subject_full);
+ $mail_message_full = str_replace('', '\''.$cur_posting['subject'].'\'', $mail_message_full);
+ $mail_message_full = str_replace('', $username, $mail_message_full);
+ $mail_message_full = str_replace('', $message, $mail_message_full);
+ $mail_message_full = str_replace('', $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $mail_message_full);
+ $mail_message_full = str_replace('', $pun_config['o_base_url'].'/misc.php?unsubscribe='.$tid, $mail_message_full);
+ $mail_message_full = str_replace('', $pun_config['o_board_title'].' '.$lang_common['Mailer'], $mail_message_full);
+
+ $notification_emails[$cur_subscriber['language']][0] = $mail_subject;
+ $notification_emails[$cur_subscriber['language']][1] = $mail_message;
+ $notification_emails[$cur_subscriber['language']][2] = $mail_subject_full;
+ $notification_emails[$cur_subscriber['language']][3] = $mail_message_full;
+
+ $mail_subject = $mail_message = $mail_subject_full = $mail_message_full = null;
+ }
+ }
+
+ // We have to double check here because the templates could be missing
+ if (isset($notification_emails[$cur_subscriber['language']]))
+ {
+ if ($cur_subscriber['notify_with_post'] == '0')
+ pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][0], $notification_emails[$cur_subscriber['language']][1]);
+ else
+ pun_mail($cur_subscriber['email'], $notification_emails[$cur_subscriber['language']][2], $notification_emails[$cur_subscriber['language']][3]);
+ }
+ }
+ }
+ }
+ }
+ // If it's a new topic
+ else if ($fid)
+ {
+ // Create the topic
+ $db->query('INSERT INTO '.$db->prefix.'topics (poster, subject, posted, last_post, last_poster, forum_id) VALUES(\''.$db->escape($username).'\', \''.$db->escape($subject).'\', '.$now.', '.$now.', \''.$db->escape($username).'\', '.$fid.')') or error('Unable to create topic', __FILE__, __LINE__, $db->error());
+ $new_tid = $db->insert_id();
+
+ if (!$pun_user['is_guest'])
+ {
+ // To subscribe or not to subscribe, that ...
+ if ($pun_config['o_subscriptions'] == '1' && $subscribe)
+ $db->query('INSERT INTO '.$db->prefix.'subscriptions (user_id, topic_id) VALUES('.$pun_user['id'].' ,'.$new_tid.')') or error('Unable to add subscription', __FILE__, __LINE__, $db->error());
+
+ // Create the post ("topic post")
+ $db->query('INSERT INTO '.$db->prefix.'posts (poster, poster_id, poster_ip, message, hide_smilies, posted, topic_id) VALUES(\''.$db->escape($username).'\', '.$pun_user['id'].', \''.get_remote_address().'\', \''.$db->escape($message).'\', '.$hide_smilies.', '.$now.', '.$new_tid.')') or error('Unable to create post', __FILE__, __LINE__, $db->error());
+ }
+ else
+ {
+ // Create the post ("topic post")
+ $email_sql = ($pun_config['p_force_guest_email'] == '1' || $email != '') ? '\''.$email.'\'' : 'NULL';
+ $db->query('INSERT INTO '.$db->prefix.'posts (poster, poster_ip, poster_email, message, hide_smilies, posted, topic_id) VALUES(\''.$db->escape($username).'\', \''.get_remote_address().'\', '.$email_sql.', \''.$db->escape($message).'\', '.$hide_smilies.', '.$now.', '.$new_tid.')') or error('Unable to create post', __FILE__, __LINE__, $db->error());
+ }
+ $new_pid = $db->insert_id();
+
+ // Update the topic with last_post_id
+ $db->query('UPDATE '.$db->prefix.'topics SET last_post_id='.$new_pid.', first_post_id='.$new_pid.' WHERE id='.$new_tid) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
+
+ update_search_index('post', $new_pid, $message, $subject);
+
+ update_forum($fid);
+ }
+
+ // If we previously found out that the email was banned
+ if ($pun_user['is_guest'] && $banned_email && $pun_config['o_mailing_list'] != '')
+ {
+ $mail_subject = $lang_common['Banned email notification'];
+ $mail_message = sprintf($lang_common['Banned email post message'], $username, $email)."\n";
+ $mail_message .= sprintf($lang_common['Post URL'], $pun_config['o_base_url'].'/viewtopic.php?pid='.$new_pid.'#p'.$new_pid)."\n";
+ $mail_message .= "\n".'--'."\n".$lang_common['Email signature'];
+
+ pun_mail($pun_config['o_mailing_list'], $mail_subject, $mail_message);
+ }
+
+ // If the posting user is logged in, increment his/her post count
+ if (!$pun_user['is_guest'])
+ {
+ $db->query('UPDATE '.$db->prefix.'users SET num_posts=num_posts+1, last_post='.$now.' WHERE id='.$pun_user['id']) or error('Unable to update user', __FILE__, __LINE__, $db->error());
+
+ $tracked_topics = get_tracked_topics();
+ $tracked_topics['topics'][$new_tid] = time();
+ set_tracked_topics($tracked_topics);
+ }
+ else
+ {
+ $db->query('UPDATE '.$db->prefix.'online SET last_post='.$now.' WHERE ident=\''.$db->escape(get_remote_address()).'\'' ) or error('Unable to update user', __FILE__, __LINE__, $db->error());
+ }
+
+ redirect('viewtopic.php?pid='.$new_pid.'#p'.$new_pid, $lang_post['Post redirect']);
+ }
+}
+
+
+// If a topic ID was specified in the url (it's a reply)
+if ($tid)
+{
+ $action = $lang_post['Post a reply'];
+ $form = '
-
-
-query('SELECT b.id, b.username, b.ip, b.email, b.message, b.expire, b.ban_creator, u.username AS ban_creator_username FROM '.$db->prefix.'bans AS b LEFT JOIN '.$db->prefix.'users AS u ON b.ban_creator=u.id WHERE b.id>0'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '').' ORDER BY '.$db->escape($order_by).' '.$db->escape($direction).' LIMIT '.$start_from.', 50') or error('Unable to fetch ban list', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- {
- while ($ban_data = $db->fetch_assoc($result))
- {
-
- $actions = ''.$lang_admin_common['Edit'].' | '.$lang_admin_common['Remove'].'';
- $expire = format_time($ban_data['expire'], true);
-
-?>
-
-
-
-query('INSERT INTO '.$db->prefix.'categories (cat_name) VALUES(\''.$db->escape($new_cat_name).'\')') or error('Unable to create category', __FILE__, __LINE__, $db->error());
-
- redirect('admin_categories.php', $lang_admin_categories['Category added redirect']);
-}
-
-// Delete a category
-else if (isset($_POST['del_cat']) || isset($_POST['del_cat_comply']))
-{
- confirm_referrer('admin_categories.php');
-
- $cat_to_delete = intval($_POST['cat_to_delete']);
- if ($cat_to_delete < 1)
- message($lang_common['Bad request']);
-
- if (isset($_POST['del_cat_comply'])) // Delete a category with all forums and posts
- {
- @set_time_limit(0);
-
- $result = $db->query('SELECT id FROM '.$db->prefix.'forums WHERE cat_id='.$cat_to_delete) or error('Unable to fetch forum list', __FILE__, __LINE__, $db->error());
- $num_forums = $db->num_rows($result);
-
- for ($i = 0; $i < $num_forums; ++$i)
- {
- $cur_forum = $db->result($result, $i);
-
- // Prune all posts and topics
- prune($cur_forum, 1, -1);
-
- // Delete the forum
- $db->query('DELETE FROM '.$db->prefix.'forums WHERE id='.$cur_forum) or error('Unable to delete forum', __FILE__, __LINE__, $db->error());
- }
-
- // Locate any "orphaned redirect topics" and delete them
- $result = $db->query('SELECT t1.id FROM '.$db->prefix.'topics AS t1 LEFT JOIN '.$db->prefix.'topics AS t2 ON t1.moved_to=t2.id WHERE t2.id IS NULL AND t1.moved_to IS NOT NULL') or error('Unable to fetch redirect topics', __FILE__, __LINE__, $db->error());
- $num_orphans = $db->num_rows($result);
-
- if ($num_orphans)
- {
- for ($i = 0; $i < $num_orphans; ++$i)
- $orphans[] = $db->result($result, $i);
-
- $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $orphans).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
- }
-
- // Delete the category
- $db->query('DELETE FROM '.$db->prefix.'categories WHERE id='.$cat_to_delete) or error('Unable to delete category', __FILE__, __LINE__, $db->error());
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_categories.php', $lang_admin_categories['Category deleted redirect']);
- }
- else // If the user hasn't comfirmed the delete
- {
- $result = $db->query('SELECT cat_name FROM '.$db->prefix.'categories WHERE id='.$cat_to_delete) or error('Unable to fetch category info', __FILE__, __LINE__, $db->error());
- $cat_name = $db->result($result);
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Categories']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
- generate_admin_menu('categories');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT id, disp_position FROM '.$db->prefix.'categories ORDER BY disp_position') or error('Unable to fetch category list', __FILE__, __LINE__, $db->error());
- $num_cats = $db->num_rows($result);
-
- for ($i = 0; $i < $num_cats; ++$i)
- {
- if ($cat_name[$i] == '')
- message($lang_admin_categories['Must enter name message']);
-
- if ($cat_order[$i] == '' || preg_match('/[^0-9]/', $cat_order[$i]))
- message($lang_admin_categories['Must enter integer message']);
-
- list($cat_id, $position) = $db->fetch_row($result);
-
- $db->query('UPDATE '.$db->prefix.'categories SET cat_name=\''.$db->escape($cat_name[$i]).'\', disp_position='.$cat_order[$i].' WHERE id='.$cat_id) or error('Unable to update category', __FILE__, __LINE__, $db->error());
- }
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_categories.php', $lang_admin_categories['Categories updated redirect']);
-}
-
-// Generate an array with all categories
-$result = $db->query('SELECT id, cat_name, disp_position FROM '.$db->prefix.'categories ORDER BY disp_position') or error('Unable to fetch category list', __FILE__, __LINE__, $db->error());
-$num_cats = $db->num_rows($result);
-
-for ($i = 0; $i < $num_cats; ++$i)
- $cat_list[] = $db->fetch_row($result);
-
-$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Categories']);
-define('PUN_ACTIVE_PAGE', 'admin');
-require PUN_ROOT.'header.php';
-
-generate_admin_menu('categories');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('INSERT INTO '.$db->prefix.'censoring (search_for, replace_with) VALUES (\''.$db->escape($search_for).'\', \''.$db->escape($replace_with).'\')') or error('Unable to add censor word', __FILE__, __LINE__, $db->error());
-
- redirect('admin_censoring.php', $lang_admin_censoring['Word added redirect']);
-}
-
-// Update a censor word
-else if (isset($_POST['update']))
-{
- confirm_referrer('admin_censoring.php');
-
- $id = intval(key($_POST['update']));
-
- $search_for = pun_trim($_POST['search_for'][$id]);
- $replace_with = pun_trim($_POST['replace_with'][$id]);
-
- if ($search_for == '' || $replace_with == '')
- message($lang_admin_censoring['Must search both message']);
-
- $db->query('UPDATE '.$db->prefix.'censoring SET search_for=\''.$db->escape($search_for).'\', replace_with=\''.$db->escape($replace_with).'\' WHERE id='.$id) or error('Unable to update censor word', __FILE__, __LINE__, $db->error());
-
- redirect('admin_censoring.php', $lang_admin_censoring['Word updated redirect']);
-}
-
-// Remove a censor word
-else if (isset($_POST['remove']))
-{
- confirm_referrer('admin_censoring.php');
-
- $id = intval(key($_POST['remove']));
-
- $db->query('DELETE FROM '.$db->prefix.'censoring WHERE id='.$id) or error('Unable to delete censor word', __FILE__, __LINE__, $db->error());
-
- redirect('admin_censoring.php', $lang_admin_censoring['Word removed redirect']);
-}
-
-$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Censoring']);
-$focus_element = array('censoring', 'new_search_for');
-define('PUN_ACTIVE_PAGE', 'admin');
-require PUN_ROOT.'header.php';
-
-generate_admin_menu('censoring');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('INSERT INTO '.$db->prefix.'forums (cat_id) VALUES('.$add_to_cat.')') or error('Unable to create forum', __FILE__, __LINE__, $db->error());
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_forums.php', $lang_admin_forums['Forum added redirect']);
-}
-
-// Delete a forum
-else if (isset($_GET['del_forum']))
-{
- confirm_referrer('admin_forums.php');
-
- $forum_id = intval($_GET['del_forum']);
- if ($forum_id < 1)
- message($lang_common['Bad request']);
-
- if (isset($_POST['del_forum_comply'])) // Delete a forum with all posts
- {
- @set_time_limit(0);
-
- // Prune all posts and topics
- prune($forum_id, 1, -1);
-
- // Locate any "orphaned redirect topics" and delete them
- $result = $db->query('SELECT t1.id FROM '.$db->prefix.'topics AS t1 LEFT JOIN '.$db->prefix.'topics AS t2 ON t1.moved_to=t2.id WHERE t2.id IS NULL AND t1.moved_to IS NOT NULL') or error('Unable to fetch redirect topics', __FILE__, __LINE__, $db->error());
- $num_orphans = $db->num_rows($result);
-
- if ($num_orphans)
- {
- for ($i = 0; $i < $num_orphans; ++$i)
- $orphans[] = $db->result($result, $i);
-
- $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.implode(',', $orphans).')') or error('Unable to delete redirect topics', __FILE__, __LINE__, $db->error());
- }
-
- // Delete the forum and any forum specific group permissions
- $db->query('DELETE FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to delete forum', __FILE__, __LINE__, $db->error());
- $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_forums.php', $lang_admin_forums['Forum deleted redirect']);
- }
- else // If the user hasn't confirmed the delete
- {
- $result = $db->query('SELECT forum_name FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
- $forum_name = pun_htmlspecialchars($db->result($result));
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Forums']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
- generate_admin_menu('forums');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
- $disp_position)
- {
- $disp_position = trim($disp_position);
- if ($disp_position == '' || preg_match('/[^0-9]/', $disp_position))
- message($lang_admin_forums['Must be integer message']);
-
- $db->query('UPDATE '.$db->prefix.'forums SET disp_position='.$disp_position.' WHERE id='.intval($forum_id)) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
- }
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_forums.php', $lang_admin_forums['Forums updated redirect']);
-}
-
-else if (isset($_GET['edit_forum']))
-{
- $forum_id = intval($_GET['edit_forum']);
- if ($forum_id < 1)
- message($lang_common['Bad request']);
-
- // Update group permissions for $forum_id
- if (isset($_POST['save']))
- {
- confirm_referrer('admin_forums.php');
-
- // Start with the forum details
- $forum_name = pun_trim($_POST['forum_name']);
- $forum_desc = pun_linebreaks(pun_trim($_POST['forum_desc']));
- $cat_id = intval($_POST['cat_id']);
- $sort_by = intval($_POST['sort_by']);
- $redirect_url = isset($_POST['redirect_url']) ? trim($_POST['redirect_url']) : null;
-
- if ($forum_name == '')
- message($lang_admin_forums['Must enter name message']);
-
- if ($cat_id < 1)
- message($lang_common['Bad request']);
-
- $forum_desc = ($forum_desc != '') ? '\''.$db->escape($forum_desc).'\'' : 'NULL';
- $redirect_url = ($redirect_url != '') ? '\''.$db->escape($redirect_url).'\'' : 'NULL';
-
- $db->query('UPDATE '.$db->prefix.'forums SET forum_name=\''.$db->escape($forum_name).'\', forum_desc='.$forum_desc.', redirect_url='.$redirect_url.', sort_by='.$sort_by.', cat_id='.$cat_id.' WHERE id='.$forum_id) or error('Unable to update forum', __FILE__, __LINE__, $db->error());
-
- // Now let's deal with the permissions
- if (isset($_POST['read_forum_old']))
- {
- $result = $db->query('SELECT g_id, g_read_board, g_post_replies, g_post_topics FROM '.$db->prefix.'groups WHERE g_id!='.PUN_ADMIN) or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
- while ($cur_group = $db->fetch_assoc($result))
- {
- $read_forum_new = ($cur_group['g_read_board'] == '1') ? isset($_POST['read_forum_new'][$cur_group['g_id']]) ? '1' : '0' : intval($_POST['read_forum_old'][$cur_group['g_id']]);
- $post_replies_new = isset($_POST['post_replies_new'][$cur_group['g_id']]) ? '1' : '0';
- $post_topics_new = isset($_POST['post_topics_new'][$cur_group['g_id']]) ? '1' : '0';
-
- // Check if the new settings differ from the old
- if ($read_forum_new != $_POST['read_forum_old'][$cur_group['g_id']] || $post_replies_new != $_POST['post_replies_old'][$cur_group['g_id']] || $post_topics_new != $_POST['post_topics_old'][$cur_group['g_id']])
- {
- // If the new settings are identical to the default settings for this group, delete it's row in forum_perms
- if ($read_forum_new == '1' && $post_replies_new == $cur_group['g_post_replies'] && $post_topics_new == $cur_group['g_post_topics'])
- $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE group_id='.$cur_group['g_id'].' AND forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
- else
- {
- // Run an UPDATE and see if it affected a row, if not, INSERT
- $db->query('UPDATE '.$db->prefix.'forum_perms SET read_forum='.$read_forum_new.', post_replies='.$post_replies_new.', post_topics='.$post_topics_new.' WHERE group_id='.$cur_group['g_id'].' AND forum_id='.$forum_id) or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
- if (!$db->affected_rows())
- $db->query('INSERT INTO '.$db->prefix.'forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) VALUES('.$cur_group['g_id'].', '.$forum_id.', '.$read_forum_new.', '.$post_replies_new.', '.$post_topics_new.')') or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
- }
- }
- }
- }
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_forums.php', $lang_admin_forums['Forum updated redirect']);
- }
- else if (isset($_POST['revert_perms']))
- {
- confirm_referrer('admin_forums.php');
-
- $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE forum_id='.$forum_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_forums.php?edit_forum='.$forum_id, $lang_admin_forums['Perms reverted redirect']);
- }
-
- // Fetch forum info
- $result = $db->query('SELECT id, forum_name, forum_desc, redirect_url, num_topics, sort_by, cat_id FROM '.$db->prefix.'forums WHERE id='.$forum_id) or error('Unable to fetch forum info', __FILE__, __LINE__, $db->error());
- if (!$db->num_rows($result))
- message($lang_common['Bad request']);
-
- $cur_forum = $db->fetch_assoc($result);
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Forums']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
- generate_admin_menu('forums');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.disp_position FROM '.$db->prefix.'categories AS c INNER JOIN '.$db->prefix.'forums AS f ON c.id=f.cat_id ORDER BY c.disp_position, c.id, f.disp_position') or error('Unable to fetch category/forum list', __FILE__, __LINE__, $db->error());
-
-if ($db->num_rows($result) > 0)
-{
-
-?>
-
-
-
-
-fetch_assoc($result))
-{
- if ($cur_forum['cid'] != $cur_category) // A new category since last iteration?
- {
- if ($cur_category != 0)
- echo "\t\t\t\t\t\t\t".''."\n\t\t\t\t\t\t\t".''."\n\t\t\t\t\t\t".'
'."\n\t\t\t\t\t".''."\n\t\t\t\t".'
'."\n";
-
-?>
-
-
-
-
-
-
-
-
-
-
-query('SELECT * FROM '.$db->prefix.'groups WHERE g_id='.$base_group) or error('Unable to fetch user group info', __FILE__, __LINE__, $db->error());
- $group = $db->fetch_assoc($result);
-
- $mode = 'add';
- }
- else // We are editing a group
- {
- $group_id = intval($_GET['edit_group']);
- if ($group_id < 1)
- message($lang_common['Bad request']);
-
- $result = $db->query('SELECT * FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to fetch user group info', __FILE__, __LINE__, $db->error());
- if (!$db->num_rows($result))
- message($lang_common['Bad request']);
-
- $group = $db->fetch_assoc($result);
-
- $mode = 'edit';
- }
-
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['User groups']);
- $required_fields = array('req_title' => $lang_admin_groups['Group title label']);
- $focus_element = array('groups2', 'req_title');
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
- generate_admin_menu('groups');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-escape($user_title).'\'' : 'NULL';
-
- if ($_POST['mode'] == 'add')
- {
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\'') or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- message(sprintf($lang_admin_groups['Title already exists message'], pun_htmlspecialchars($title)));
-
- $db->query('INSERT INTO '.$db->prefix.'groups (g_title, g_user_title, g_moderator, g_mod_edit_users, g_mod_rename_users, g_mod_change_passwords, g_mod_ban_users, g_read_board, g_view_users, g_post_replies, g_post_topics, g_edit_posts, g_delete_posts, g_delete_topics, g_set_title, g_search, g_search_users, g_send_email, g_post_flood, g_search_flood, g_email_flood) VALUES(\''.$db->escape($title).'\', '.$user_title.', '.$moderator.', '.$mod_edit_users.', '.$mod_rename_users.', '.$mod_change_passwords.', '.$mod_ban_users.', '.$read_board.', '.$view_users.', '.$post_replies.', '.$post_topics.', '.$edit_posts.', '.$delete_posts.', '.$delete_topics.', '.$set_title.', '.$search.', '.$search_users.', '.$send_email.', '.$post_flood.', '.$search_flood.', '.$email_flood.')') or error('Unable to add group', __FILE__, __LINE__, $db->error());
- $new_group_id = $db->insert_id();
-
- // Now lets copy the forum specific permissions from the group which this group is based on
- $result = $db->query('SELECT forum_id, read_forum, post_replies, post_topics FROM '.$db->prefix.'forum_perms WHERE group_id='.intval($_POST['base_group'])) or error('Unable to fetch group forum permission list', __FILE__, __LINE__, $db->error());
- while ($cur_forum_perm = $db->fetch_assoc($result))
- $db->query('INSERT INTO '.$db->prefix.'forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) VALUES('.$new_group_id.', '.$cur_forum_perm['forum_id'].', '.$cur_forum_perm['read_forum'].', '.$cur_forum_perm['post_replies'].', '.$cur_forum_perm['post_topics'].')') or error('Unable to insert group forum permissions', __FILE__, __LINE__, $db->error());
- }
- else
- {
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_title=\''.$db->escape($title).'\' AND g_id!='.intval($_POST['group_id'])) or error('Unable to check group title collision', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- message(sprintf($lang_admin_groups['Title already exists message'], pun_htmlspecialchars($title)));
-
- $db->query('UPDATE '.$db->prefix.'groups SET g_title=\''.$db->escape($title).'\', g_user_title='.$user_title.', g_moderator='.$moderator.', g_mod_edit_users='.$mod_edit_users.', g_mod_rename_users='.$mod_rename_users.', g_mod_change_passwords='.$mod_change_passwords.', g_mod_ban_users='.$mod_ban_users.', g_read_board='.$read_board.', g_view_users='.$view_users.', g_post_replies='.$post_replies.', g_post_topics='.$post_topics.', g_edit_posts='.$edit_posts.', g_delete_posts='.$delete_posts.', g_delete_topics='.$delete_topics.', g_set_title='.$set_title.', g_search='.$search.', g_search_users='.$search_users.', g_send_email='.$send_email.', g_post_flood='.$post_flood.', g_search_flood='.$search_flood.', g_email_flood='.$email_flood.' WHERE g_id='.intval($_POST['group_id'])) or error('Unable to update group', __FILE__, __LINE__, $db->error());
- }
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- if ($_POST['mode'] == 'edit')
- redirect('admin_groups.php', $lang_admin_groups['Group edited redirect']);
- else
- redirect('admin_groups.php', $lang_admin_groups['Group added redirect']);
-}
-
-
-// Set default group
-else if (isset($_POST['set_default_group']))
-{
- confirm_referrer('admin_groups.php');
-
- $group_id = intval($_POST['default_group']);
-
- // Make sure it's not the admin or guest groups
- if ($group_id == PUN_ADMIN || $group_id == PUN_GUEST)
- message($lang_common['Bad request']);
-
- // Make sure it's not a moderator group
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'groups WHERE g_id='.$group_id.' AND g_moderator=0') or error('Unable to check group moderator status', __FILE__, __LINE__, $db->error());
- if (!$db->num_rows($result))
- message($lang_common['Bad request']);
-
- $db->query('UPDATE '.$db->prefix.'config SET conf_value='.$group_id.' WHERE conf_name=\'o_default_user_group\'') or error('Unable to update board config', __FILE__, __LINE__, $db->error());
-
- // Regenerate the config cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_config_cache();
-
- redirect('admin_groups.php', $lang_admin_groups['Default group redirect']);
-}
-
-
-// Remove a group
-else if (isset($_GET['del_group']))
-{
- confirm_referrer('admin_groups.php');
-
- $group_id = isset($_POST['group_to_delete']) ? intval($_POST['group_to_delete']) : intval($_GET['del_group']);
- if ($group_id < 5)
- message($lang_common['Bad request']);
-
- // Make sure we don't remove the default group
- if ($group_id == $pun_config['o_default_user_group'])
- message($lang_admin_groups['Cannot remove default message']);
-
- // Check if this group has any members
- $result = $db->query('SELECT g.g_title, COUNT(u.id) FROM '.$db->prefix.'groups AS g INNER JOIN '.$db->prefix.'users AS u ON g.g_id=u.group_id WHERE g.g_id='.$group_id.' GROUP BY g.g_id, g_title') or error('Unable to fetch group info', __FILE__, __LINE__, $db->error());
-
- // If the group doesn't have any members or if we've already selected a group to move the members to
- if (!$db->num_rows($result) || isset($_POST['del_group']))
- {
- if (isset($_POST['del_group_comply']) || isset($_POST['del_group']))
- {
- if (isset($_POST['del_group']))
- {
- $move_to_group = intval($_POST['move_to_group']);
- $db->query('UPDATE '.$db->prefix.'users SET group_id='.$move_to_group.' WHERE group_id='.$group_id) or error('Unable to move users into group', __FILE__, __LINE__, $db->error());
- }
-
- // Delete the group and any forum specific permissions
- $db->query('DELETE FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to delete group', __FILE__, __LINE__, $db->error());
- $db->query('DELETE FROM '.$db->prefix.'forum_perms WHERE group_id='.$group_id) or error('Unable to delete group forum permissions', __FILE__, __LINE__, $db->error());
-
- // Regenerate the quick jump cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_quickjump_cache();
-
- redirect('admin_groups.php', $lang_admin_groups['Group removed redirect']);
- }
- else
- {
- $result = $db->query('SELECT g_title FROM '.$db->prefix.'groups WHERE g_id='.$group_id) or error('Unable to fetch group title', __FILE__, __LINE__, $db->error());
- $group_title = $db->result($result);
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['User groups']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
- generate_admin_menu('groups');
-
-?>
-
'."\n";
-
- if ($cur_item['id'] == $cur_item['first_post_id'])
- update_search_index('post', $cur_item['id'], $cur_item['message'], $cur_item['subject']);
- else
- update_search_index('post', $cur_item['id'], $cur_item['message']);
-
- $end_at = $cur_item['id'];
- }
-
- // Check if there is more work to do
- if ($end_at > 0)
- {
- $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE id > '.$end_at.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch next ID', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result) > 0)
- $query_str = '?i_per_page='.$per_page.'&i_start_at='.$db->result($result);
- }
-
- $db->end_transaction();
- $db->close();
-
- exit('
');
-}
-
-
-// Get the first post ID from the db
-$result = $db->query('SELECT id FROM '.$db->prefix.'posts ORDER BY id ASC LIMIT 1') or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
-if ($db->num_rows($result))
- $first_id = $db->result($result);
-
-$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Maintenance']);
-define('PUN_ACTIVE_PAGE', 'admin');
-require PUN_ROOT.'header.php';
-
-generate_admin_menu('maintenance');
-
-?>
-
-
-
-query('SELECT 1 FROM '.$db->prefix.'ranks WHERE min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- message(sprintf($lang_admin_ranks['Dupe min posts message'], $min_posts));
-
- $db->query('INSERT INTO '.$db->prefix.'ranks (rank, min_posts) VALUES(\''.$db->escape($rank).'\', '.$min_posts.')') or error('Unable to add rank', __FILE__, __LINE__, $db->error());
-
- // Regenerate the ranks cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_ranks_cache();
-
- redirect('admin_ranks.php', $lang_admin_ranks['Rank added redirect']);
-}
-
-
-// Update a rank
-else if (isset($_POST['update']))
-{
- confirm_referrer('admin_ranks.php');
-
- $id = intval(key($_POST['update']));
-
- $rank = pun_trim($_POST['rank'][$id]);
- $min_posts = trim($_POST['min_posts'][$id]);
-
- if ($rank == '')
- message($lang_admin_ranks['Must enter title message']);
-
- if ($min_posts == '' || preg_match('/[^0-9]/', $min_posts))
- message($lang_admin_ranks['Must be integer message']);
-
- // Make sure there isn't already a rank with the same min_posts value
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'ranks WHERE id!='.$id.' AND min_posts='.$min_posts) or error('Unable to fetch rank info', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- message(sprintf($lang_admin_ranks['Dupe min posts message'], $min_posts));
-
- $db->query('UPDATE '.$db->prefix.'ranks SET rank=\''.$db->escape($rank).'\', min_posts='.$min_posts.' WHERE id='.$id) or error('Unable to update rank', __FILE__, __LINE__, $db->error());
-
- // Regenerate the ranks cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_ranks_cache();
-
- redirect('admin_ranks.php', $lang_admin_ranks['Rank updated redirect']);
-}
-
-
-// Remove a rank
-else if (isset($_POST['remove']))
-{
- confirm_referrer('admin_ranks.php');
-
- $id = intval(key($_POST['remove']));
-
- $db->query('DELETE FROM '.$db->prefix.'ranks WHERE id='.$id) or error('Unable to delete rank', __FILE__, __LINE__, $db->error());
-
- // Regenerate the ranks cache
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_ranks_cache();
-
- redirect('admin_ranks.php', $lang_admin_ranks['Rank removed redirect']);
-}
-
-$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Ranks']);
-$focus_element = array('ranks', 'new_rank');
-define('PUN_ACTIVE_PAGE', 'admin');
-require PUN_ROOT.'header.php';
-
-generate_admin_menu('ranks');
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT zapped FROM '.$db->prefix.'reports WHERE id='.$zap_id) or error('Unable to fetch report info', __FILE__, __LINE__, $db->error());
- $zapped = $db->result($result);
-
- if ($zapped == '')
- $db->query('UPDATE '.$db->prefix.'reports SET zapped='.time().', zapped_by='.$pun_user['id'].' WHERE id='.$zap_id) or error('Unable to zap report', __FILE__, __LINE__, $db->error());
-
- redirect('admin_reports.php', $lang_admin_reports['Report zapped redirect']);
-}
-
-
-$page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Reports']);
-define('PUN_ACTIVE_PAGE', 'admin');
-require PUN_ROOT.'header.php';
-
-generate_admin_menu('reports');
-
-?>
-
-
-
-
-query('SELECT r.id, r.topic_id, r.forum_id, r.reported_by, r.created, r.message, p.id AS pid, t.subject, f.forum_name, u.username AS reporter FROM '.$db->prefix.'reports AS r LEFT JOIN '.$db->prefix.'posts AS p ON r.post_id=p.id LEFT JOIN '.$db->prefix.'topics AS t ON r.topic_id=t.id LEFT JOIN '.$db->prefix.'forums AS f ON r.forum_id=f.id LEFT JOIN '.$db->prefix.'users AS u ON r.reported_by=u.id WHERE r.zapped IS NULL ORDER BY created DESC') or error('Unable to fetch report list', __FILE__, __LINE__, $db->error());
-
-if ($db->num_rows($result))
-{
- while ($cur_report = $db->fetch_assoc($result))
- {
- $reporter = ($cur_report['reporter'] != '') ? ''.pun_htmlspecialchars($cur_report['reporter']).'' : $lang_admin_reports['Deleted user'];
- $forum = ($cur_report['forum_name'] != '') ? ''.pun_htmlspecialchars($cur_report['forum_name']).'' : $lang_admin_reports['Deleted'];
- $topic = ($cur_report['subject'] != '') ? ''.pun_htmlspecialchars($cur_report['subject']).'' : $lang_admin_reports['Deleted'];
- $post = str_replace("\n", ' ', pun_htmlspecialchars($cur_report['message']));
- $postid = ($cur_report['pid'] != '') ? 'Post #'.$cur_report['pid'].'' : $lang_admin_reports['Deleted'];
- $report_location = array($forum, $topic, $postid);
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT r.id, r.topic_id, r.forum_id, r.reported_by, r.message, r.zapped, r.zapped_by AS zapped_by_id, p.id AS pid, t.subject, f.forum_name, u.username AS reporter, u2.username AS zapped_by FROM '.$db->prefix.'reports AS r LEFT JOIN '.$db->prefix.'posts AS p ON r.post_id=p.id LEFT JOIN '.$db->prefix.'topics AS t ON r.topic_id=t.id LEFT JOIN '.$db->prefix.'forums AS f ON r.forum_id=f.id LEFT JOIN '.$db->prefix.'users AS u ON r.reported_by=u.id LEFT JOIN '.$db->prefix.'users AS u2 ON r.zapped_by=u2.id WHERE r.zapped IS NOT NULL ORDER BY zapped DESC LIMIT 10') or error('Unable to fetch report list', __FILE__, __LINE__, $db->error());
-
-if ($db->num_rows($result))
-{
- while ($cur_report = $db->fetch_assoc($result))
- {
- $reporter = ($cur_report['reporter'] != '') ? ''.pun_htmlspecialchars($cur_report['reporter']).'' : $lang_admin_reports['Deleted user'];
- $forum = ($cur_report['forum_name'] != '') ? ''.pun_htmlspecialchars($cur_report['forum_name']).'' : $lang_admin_reports['Deleted'];
- $topic = ($cur_report['subject'] != '') ? ''.pun_htmlspecialchars($cur_report['subject']).'' : $lang_admin_reports['Deleted'];
- $post = str_replace("\n", ' ', pun_htmlspecialchars($cur_report['message']));
- $post_id = ($cur_report['pid'] != '') ? 'Post #'.$cur_report['pid'].'' : $lang_admin_reports['Deleted'];
- $zapped_by = ($cur_report['zapped_by'] != '') ? ''.pun_htmlspecialchars($cur_report['zapped_by']).'' : $lang_admin_reports['NA'];
- $zapped_by = ($cur_report['zapped_by'] != '') ? ''.pun_htmlspecialchars($cur_report['zapped_by']).'' : $lang_admin_reports['NA'];
- $report_location = array($forum, $topic, $post_id);
-
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT poster_ip, MAX(posted) AS last_used FROM '.$db->prefix.'posts WHERE poster_id='.$ip_stats.' GROUP BY poster_ip') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
- $num_ips = $db->num_rows($result);
-
- // Determine the ip offset (based on $_GET['p'])
- $num_pages = ceil($num_ips / 50);
-
- $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
- $start_from = 50 * ($p - 1);
-
- // Generate paging links
- $paging_links = ''.$lang_common['Pages'].' '.paginate($num_pages, $p, 'admin_users.php?ip_stats='.$ip_stats );
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Users'], $lang_admin_users['Results head']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
-?>
-
-
-
-
-
»
-
»
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT poster_ip, MAX(posted) AS last_used, COUNT(id) AS used_times FROM '.$db->prefix.'posts WHERE poster_id='.$ip_stats.' GROUP BY poster_ip ORDER BY last_used DESC LIMIT '.$start_from.', 50') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- {
- while ($cur_ip = $db->fetch_assoc($result))
- {
-
-?>
-
-
-
-query('SELECT DISTINCT poster_id, poster FROM '.$db->prefix.'posts WHERE poster_ip=\''.$db->escape($ip).'\' ORDER BY poster DESC') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
- $num_posts = $db->num_rows($result);
-
- if ($num_posts)
- {
- // Loop through users and print out some info
- for ($i = 0; $i < $num_posts; ++$i)
- {
- list($poster_id, $poster) = $db->fetch_row($result);
-
- $result2 = $db->query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1 AND u.id='.$poster_id) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
-
- if (($user_data = $db->fetch_assoc($result2)))
- {
- $user_title = get_title($user_data);
-
- $actions = ''.$lang_admin_users['Results view IP link'].' | '.$lang_admin_users['Results show posts link'].'';
-
-?>
-
-'.$last_post_after;
- }
- if ($last_post_before != '')
- {
- $query_str[] = 'last_post_before='.$last_post_before;
-
- $last_post_before = strtotime($last_post_before);
- if ($last_post_before === false || $last_post_before == -1)
- message($lang_admin_users['Invalid date time message']);
-
- $conditions[] = 'u.last_post<'.$last_post_before;
- }
- if ($registered_after != '')
- {
- $query_str[] = 'registered_after='.$registered_after;
-
- $registered_after = strtotime($registered_after);
- if ($registered_after === false || $registered_after == -1)
- message($lang_admin_users['Invalid date time message']);
-
- $conditions[] = 'u.registered>'.$registered_after;
- }
- if ($registered_before != '')
- {
- $query_str[] = 'registered_before='.$registered_before;
-
- $registered_before = strtotime($registered_before);
- if ($registered_before === false || $registered_before == -1)
- message($lang_admin_users['Invalid date time message']);
-
- $conditions[] = 'u.registered<'.$registered_before;
- }
-
- $like_command = ($db_type == 'pgsql') ? 'ILIKE' : 'LIKE';
- while (list($key, $input) = @each($form))
- {
- if ($input != '' && in_array($key, array('username', 'email', 'title', 'realname', 'url', 'jabber', 'icq', 'msn', 'aim', 'yahoo', 'location', 'signature', 'admin_note')))
- {
- $conditions[] = 'u.'.$db->escape($key).' '.$like_command.' \''.$db->escape(str_replace('*', '%', $input)).'\'';
- $query_str[] = 'form%5B'.$key.'%5D='.urlencode($input);
- }
- }
-
- if ($posts_greater != '')
- {
- $query_str[] = 'posts_greater='.$posts_greater;
- $conditions[] = 'u.num_posts>'.$posts_greater;
- }
- if ($posts_less != '')
- {
- $query_str[] = 'posts_less='.$posts_less;
- $conditions[] = 'u.num_posts<'.$posts_less;
- }
-
- if ($user_group > -1)
- $conditions[] = 'u.group_id='.$user_group;
-
- // Fetch user count
- $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
- $num_users = $db->result($result);
-
- // Determine the user offset (based on $_GET['p'])
- $num_pages = ceil($num_users / 50);
-
- $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
- $start_from = 50 * ($p - 1);
-
- // Generate paging links
- $paging_links = ''.$lang_common['Pages'].' '.paginate($num_pages, $p, 'admin_users.php?find_user=&'.implode('&', $query_str));
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_admin_common['Admin'], $lang_admin_common['Users'], $lang_admin_users['Results head']);
- define('PUN_ACTIVE_PAGE', 'admin');
- require PUN_ROOT.'header.php';
-
-?>
-
-
-
-
-
»
-
»
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT u.id, u.username, u.email, u.title, u.num_posts, u.admin_note, g.g_id, g.g_user_title FROM '.$db->prefix.'users AS u LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id WHERE u.id>1'.(!empty($conditions) ? ' AND '.implode(' AND ', $conditions) : '').' ORDER BY '.$db->escape($order_by).' '.$db->escape($direction).' LIMIT '.$start_from.', 50') or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- {
- while ($user_data = $db->fetch_assoc($result))
- {
- $user_title = get_title($user_data);
-
- // This script is a special case in that we want to display "Not verified" for non-verified users
- if (($user_data['g_id'] == '' || $user_data['g_id'] == PUN_UNVERIFIED) && $user_title != $lang_common['Banned'])
- $user_title = ''.$lang_admin_users['Not verified'].'';
-
- $actions = ''.$lang_admin_users['Results view IP link'].' | '.$lang_admin_users['Results show posts link'].'';
-
-?>
-
-
-
-
-Order Allow,Deny
-Deny from All
-
diff --git a/upload/cache/index.html b/upload/cache/index.html
deleted file mode 100644
index 89337b2..0000000
--- a/upload/cache/index.html
+++ /dev/null
@@ -1 +0,0 @@
-..
diff --git a/upload/db_update.php b/upload/db_update.php
deleted file mode 100644
index 6cf36eb..0000000
--- a/upload/db_update.php
+++ /dev/null
@@ -1,1427 +0,0 @@
-query('SELECT conf_value FROM '.$db->prefix.'config WHERE conf_name=\'o_cur_version\'') or error('Unable to fetch version info.', __FILE__, __LINE__, $db->error());
-$cur_version = $db->result($result);
-
-if (version_compare($cur_version, '1.2', '<'))
- exit('Version mismatch. The database \''.$db_name.'\' doesn\'t seem to be running a FluxBB database schema supported by this update script.');
-
-// Do some DB type specific checks
-$mysql = false;
-switch ($db_type)
-{
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- $mysql_info = $db->get_version();
- if (version_compare($mysql_info['version'], MIN_MYSQL_VERSION, '<'))
- error('You are running MySQL version '.$mysql_version.'. FluxBB '.UPDATE_TO.' requires at least MySQL '.MIN_MYSQL_VERSION.' to run properly. You must upgrade your MySQL installation before you can continue.');
-
- $mysql = true;
- break;
-
- case 'pgsql':
- $pgsql_info = $db->get_version();
- if (version_compare($pgsql_info['version'], MIN_PGSQL_VERSION, '<'))
- error('You are running PostgreSQL version '.$pgsql_info.'. FluxBB '.UPDATE_TO.' requires at least PostgreSQL '.MIN_PGSQL_VERSION.' to run properly. You must upgrade your PostgreSQL installation before you can continue.');
-
- break;
-}
-
-// Get the forum config
-$result = $db->query('SELECT * FROM '.$db->prefix.'config') or error('Unable to fetch config.', __FILE__, __LINE__, $db->error());
-while ($cur_config_item = $db->fetch_row($result))
- $pun_config[$cur_config_item[0]] = $cur_config_item[1];
-
-// Check the database revision and the current version
-if (isset($pun_config['o_database_revision']) && $pun_config['o_database_revision'] >= UPDATE_TO_DB_REVISION && version_compare($pun_config['o_cur_version'], UPDATE_TO, '>='))
- exit('Your database is already as up-to-date as this script can make it.');
-
-$default_style = $pun_config['o_default_style'];
-if (!file_exists(PUN_ROOT.'style/'.$default_style.'.css'))
- $default_style = 'Air';
-
-//
-// Determines whether $str is UTF-8 encoded or not
-//
-function seems_utf8($str)
-{
- $str_len = strlen($str);
- for ($i = 0; $i < $str_len; ++$i)
- {
- if (ord($str[$i]) < 0x80) continue; # 0bbbbbbb
- else if ((ord($str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
- else if ((ord($str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
- else if ((ord($str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
- else if ((ord($str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
- else if ((ord($str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
- else return false; # Does not match any model
-
- for ($j = 0; $j < $n; ++$j) # n bytes matching 10bbbbbb follow ?
- {
- if ((++$i == strlen($str)) || ((ord($str[$i]) & 0xC0) != 0x80))
- return false;
- }
- }
-
- return true;
-}
-
-
-//
-// Translates the number from a HTML numeric entity into an UTF-8 character
-//
-function dcr2utf8($src)
-{
- $dest = '';
- if ($src < 0)
- return false;
- else if ($src <= 0x007f)
- $dest .= chr($src);
- else if ($src <= 0x07ff)
- {
- $dest .= chr(0xc0 | ($src >> 6));
- $dest .= chr(0x80 | ($src & 0x003f));
- }
- else if ($src == 0xFEFF)
- {
- // nop -- zap the BOM
- }
- else if ($src >= 0xD800 && $src <= 0xDFFF)
- {
- // found a surrogate
- return false;
- }
- else if ($src <= 0xffff)
- {
- $dest .= chr(0xe0 | ($src >> 12));
- $dest .= chr(0x80 | (($src >> 6) & 0x003f));
- $dest .= chr(0x80 | ($src & 0x003f));
- }
- else if ($src <= 0x10ffff)
- {
- $dest .= chr(0xf0 | ($src >> 18));
- $dest .= chr(0x80 | (($src >> 12) & 0x3f));
- $dest .= chr(0x80 | (($src >> 6) & 0x3f));
- $dest .= chr(0x80 | ($src & 0x3f));
- }
- else
- {
- // out of range
- return false;
- }
-
- return $dest;
-}
-
-
-//
-// Attempts to convert $str from $old_charset to UTF-8. Also converts HTML entities (including numeric entities) to UTF-8 characters
-//
-function convert_to_utf8(&$str, $old_charset)
-{
- if ($str === null || $str == '')
- return false;
-
- $save = $str;
-
- // Replace literal entities (for non-UTF-8 compliant html_entity_encode)
- if (version_compare(PHP_VERSION, '5.0.0', '<') && $old_charset == 'ISO-8859-1' || $old_charset == 'ISO-8859-15')
- $str = html_entity_decode($str, ENT_QUOTES, $old_charset);
-
- if ($old_charset != 'UTF-8' && !seems_utf8($str))
- {
- if (function_exists('iconv'))
- $str = iconv($old_charset == 'ISO-8859-1' ? 'WINDOWS-1252' : 'ISO-8859-1', 'UTF-8', $str);
- else if (function_exists('mb_convert_encoding'))
- $str = mb_convert_encoding($str, 'UTF-8', $old_charset == 'ISO-8859-1' ? 'WINDOWS-1252' : 'ISO-8859-1');
- else if ($old_charset == 'ISO-8859-1')
- $str = utf8_encode($str);
- }
-
- // Replace literal entities (for UTF-8 compliant html_entity_encode)
- if (version_compare(PHP_VERSION, '5.0.0', '>='))
- $str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
-
- // Replace numeric entities
- $str = preg_replace_callback('/([0-9]+);/', 'utf8_callback_1', $str);
- $str = preg_replace_callback('/([a-f0-9]+);/i', 'utf8_callback_2', $str);
-
- // Remove "bad" characters
- $str = remove_bad_characters($str);
-
- return ($save != $str);
-}
-
-
-function utf8_callback_1($matches)
-{
- return dcr2utf8($matches[1]);
-}
-
-
-function utf8_callback_2($matches)
-{
- return dcr2utf8(hexdec($matches[1]));
-}
-
-
-//
-// Alter a table to be utf8. MySQL only
-// Function based on update_convert_table_utf8() from the Drupal project (http://drupal.org/)
-//
-function alter_table_utf8($table)
-{
- global $mysql, $db;
- static $types;
-
- if (!$mysql)
- return;
-
- if (!isset($types))
- {
- $types = array(
- 'char' => 'binary',
- 'varchar' => 'varbinary',
- 'tinytext' => 'tinyblob',
- 'mediumtext' => 'mediumblob',
- 'text' => 'blob',
- 'longtext' => 'longblob'
- );
- }
-
- // Set table default charset to utf8
- $db->query('ALTER TABLE '.$table.' CHARACTER SET utf8') or error('Unable to set table character set', __FILE__, __LINE__, $db->error());
-
- // Find out which columns need converting and build SQL statements
- $result = $db->query('SHOW FULL COLUMNS FROM '.$table) or error('Unable to fetch column information', __FILE__, __LINE__, $db->error());
- while ($cur_column = $db->fetch_assoc($result))
- {
- if ($cur_column['Collation'] === null)
- continue;
-
- list($type) = explode('(', $cur_column['Type']);
- if (isset($types[$type]) && strpos($cur_column['Collation'], 'utf8') === false)
- {
- $allow_null = ($cur_column['Null'] == 'YES');
- $collate = (substr($cur_column['Collation'], -3) == 'bin') ? 'utf8_bin' : 'utf8_general_ci';
-
- $db->alter_field($table, $cur_column['Field'], preg_replace('/'.$type.'/i', $types[$type], $cur_column['Type']), $allow_null, $cur_column['Default'], null, true) or error('Unable to alter field to binary', __FILE__, __LINE__, $db->error());
- $db->alter_field($table, $cur_column['Field'], $cur_column['Type'].' CHARACTER SET utf8 COLLATE '.$collate, $allow_null, $cur_column['Default'], null, true) or error('Unable to alter field to utf8', __FILE__, __LINE__, $db->error());
- }
- }
-}
-
-//
-// Safely converts text type columns into utf8
-// If finished returns true, otherwise returns $end_at
-//
-function convert_table_utf8($table, $callback, $old_charset, $key = null, $start_at = null)
-{
- global $mysql, $db;
-
- $finished = true;
- $end_at = 0;
- if ($mysql)
- {
- // Only set up the tables if we are doing this in 1 go, or its the first go
- if ($start_at === null || $start_at == 0)
- {
- // Drop any temp table that exists, in-case it's left over from a failed update
- $db->drop_table($table.'_utf8', true) or error('Unable to drop left over temp table', __FILE__, __LINE__, $db->error());
-
- // Copy the table
- $db->query('CREATE TABLE '.$table.'_utf8 LIKE '.$table) or error('Unable to create new table', __FILE__, __LINE__, $db->error());
-
- // Set table default charset to utf8
- alter_table_utf8($table.'_utf8');
- }
-
- // Change to latin1 mode so MySQL doesn't attempt to perform conversion on the data from the old table
- $db->set_names('latin1');
-
- // Move & Convert everything
- $result = $db->query('SELECT * FROM '.$table.($start_at === null ? '' : ' WHERE '.$key.'>'.$start_at).' ORDER BY '.$key.' ASC'.($start_at === null ? '' : ' LIMIT '.PER_PAGE), false) or error('Unable to select from old table', __FILE__, __LINE__, $db->error());
-
- // Change back to utf8 mode so we can insert it into the new table
- $db->set_names('utf8');
-
- while ($cur_item = $db->fetch_assoc($result))
- {
- $cur_item = call_user_func($callback, $cur_item, $old_charset);
-
- $temp = array();
- foreach ($cur_item as $idx => $value)
- $temp[$idx] = $value === null ? 'NULL' : '\''.$db->escape($value).'\'';
-
- $db->query('INSERT INTO '.$table.'_utf8('.implode(',', array_keys($temp)).') VALUES ('.implode(',', array_values($temp)).')') or error('Unable to insert data to new table', __FILE__, __LINE__, $db->error());
-
- $end_at = $cur_item[$key];
- }
-
- // If we aren't doing this all in 1 go and $end_at has a value (i.e. we have processed at least 1 row), figure out if we have more to do or not
- if ($start_at !== null && $end_at > 0)
- {
- $result = $db->query('SELECT 1 FROM '.$table.' WHERE '.$key.'>'.$end_at.' ORDER BY '.$key.' ASC LIMIT 1') or error('Unable to check for next row', __FILE__, __LINE__, $db->error());
- $finished = $db->num_rows($result) == 0;
- }
-
- // Only swap the tables if we are doing this in 1 go, or its the last go
- if ($finished)
- {
- // Delete old table
- $db->drop_table($table, true) or error('Unable to drop old table', __FILE__, __LINE__, $db->error());
-
- // Rename table
- $db->query('ALTER TABLE '.$table.'_utf8 RENAME '.$table) or error('Unable to rename new table', __FILE__, __LINE__, $db->error());
-
- return true;
- }
-
- return $end_at;
- }
- else
- {
- // Convert everything
- $result = $db->query('SELECT * FROM '.$table.($start_at === null ? '' : ' WHERE '.$key.'>'.$start_at).' ORDER BY '.$key.' ASC'.($start_at === null ? '' : ' LIMIT '.PER_PAGE)) or error('Unable to select from table', __FILE__, __LINE__, $db->error());
- while ($cur_item = $db->fetch_assoc($result))
- {
- $cur_item = call_user_func($callback, $cur_item, $old_charset);
-
- $temp = array();
- foreach ($cur_item as $idx => $value)
- $temp[] = $idx.'='.($value === null ? 'NULL' : '\''.$db->escape($value).'\'');
-
- if (!empty($temp))
- $db->query('UPDATE '.$table.' SET '.implode(', ', $temp).' WHERE '.$key.'=\''.$db->escape($cur_item[$key]).'\'') or error('Unable to update data', __FILE__, __LINE__, $db->error());
-
- $end_at = $cur_item[$key];
- }
-
- if ($start_at !== null && $end_at > 0)
- {
- $result = $db->query('SELECT 1 FROM '.$table.' WHERE '.$key.'>'.$end_at.' ORDER BY '.$key.' ASC LIMIT 1') or error('Unable to check for next row', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result) == 0)
- return true;
-
- return $end_at;
- }
-
- return true;
- }
-}
-
-
-header('Content-type: text/html; charset=utf-8');
-
-// Empty all output buffers and stop buffering
-while (@ob_end_clean());
-
-
-$stage = isset($_GET['stage']) ? $_GET['stage'] : '';
-$old_charset = isset($_GET['req_old_charset']) ? str_replace('ISO8859', 'ISO-8859', strtoupper($_GET['req_old_charset'])) : 'ISO-8859-1';
-$start_at = isset($_GET['start_at']) ? intval($_GET['start_at']) : 0;
-$query_str = '';
-
-switch ($stage)
-{
- // Show form
- case '':
-
-?>
-
-
-
-
-
-FluxBB Database Update
-
-
-
-
-
-
-
-
-
FluxBB Update
-
-
-
-
-
This script will update your forum database. The update procedure might take anything from a second to hours depending on the speed of the server and the size of the forum database. Don't forget to make a backup of the database before continuing.
-
Did you read the update instructions in the documentation? If not, start there.
-
-
IMPORTANT! FluxBB has detected that this PHP environment does not have support for the encoding mechanisms required to do UTF-8 conversion from character sets other than ISO-8859-1. What this means is that if the current character set is not ISO-8859-1, FluxBB won't be able to convert your forum database to UTF-8 and you will have to do it manually. Instructions for doing manual charset conversion can be found in the update instructions.
-
-
-
-
Enable conversion: When enabled this update script will, after it has made the required structural changes to the database, convert all text in the database from the current character set to UTF-8. This conversion is required if you're upgrading from version 1.2.
-
Current character set: If the primary language in your forum is English, you can leave this at the default value. However, if your forum is non-English, you should enter the character set of the primary language pack used in the forum. Getting this wrong can corrupt your database so don't just guess! Note: This is required even if the old database is UTF-8.
-
-
-
-
-
-
-
-
-
-
-
-
-
-alter_field('bans', 'email', 'VARCHAR(80)', true) or error('Unable to alter email field', __FILE__, __LINE__, $db->error());
- $db->alter_field('posts', 'poster_email', 'VARCHAR(80)', true) or error('Unable to alter poster_email field', __FILE__, __LINE__, $db->error());
- $db->alter_field('users', 'email', 'VARCHAR(80)', false, '') or error('Unable to alter email field', __FILE__, __LINE__, $db->error());
- $db->alter_field('users', 'jabber', 'VARCHAR(80)', true) or error('Unable to alter jabber field', __FILE__, __LINE__, $db->error());
- $db->alter_field('users', 'msn', 'VARCHAR(80)', true) or error('Unable to alter msn field', __FILE__, __LINE__, $db->error());
- $db->alter_field('users', 'activate_string', 'VARCHAR(80)', true) or error('Unable to alter activate_string field', __FILE__, __LINE__, $db->error());
-
- // Make all IP fields VARCHAR(39) to support IPv6
- $db->alter_field('posts', 'poster_ip', 'VARCHAR(39)', true) or error('Unable to alter poster_ip field', __FILE__, __LINE__, $db->error());
- $db->alter_field('users', 'registration_ip', 'VARCHAR(39)', false, '0.0.0.0') or error('Unable to alter registration_ip field', __FILE__, __LINE__, $db->error());
-
- // Add the DST option to the users table
- $db->add_field('users', 'dst', 'TINYINT(1)', false, 0, 'timezone') or error('Unable to add dst field', __FILE__, __LINE__, $db->error());
-
- // Add the last_post field to the online table
- $db->add_field('online', 'last_post', 'INT(10) UNSIGNED', true, null, null) or error('Unable to add last_post field', __FILE__, __LINE__, $db->error());
-
- // Add the last_search field to the online table
- $db->add_field('online', 'last_search', 'INT(10) UNSIGNED', true, null, null) or error('Unable to add last_search field', __FILE__, __LINE__, $db->error());
-
- // Add the last_search column to the users table
- $db->add_field('users', 'last_search', 'INT(10) UNSIGNED', true, null, 'last_post') or error('Unable to add last_search field', __FILE__, __LINE__, $db->error());
-
- // Drop use_avatar column from users table
- $db->drop_field('users', 'use_avatar') or error('Unable to drop use_avatar field', __FILE__, __LINE__, $db->error());
-
- // Drop save_pass column from users table
- $db->drop_field('users', 'save_pass') or error('Unable to drop save_pass field', __FILE__, __LINE__, $db->error());
-
- // Drop g_edit_subjects_interval column from groups table
- $db->drop_field('groups', 'g_edit_subjects_interval');
-
- // Add database revision number
- if (!array_key_exists('o_database_revision', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_database_revision\', \'0\')') or error('Unable to insert config value \'o_database_revision\'', __FILE__, __LINE__, $db->error());
-
- // Add default email setting option
- if (!array_key_exists('o_default_email_setting', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_default_email_setting\', \'1\')') or error('Unable to insert config value \'o_default_email_setting\'', __FILE__, __LINE__, $db->error());
-
- // Make sure we have o_additional_navlinks (was added in 1.2.1)
- if (!array_key_exists('o_additional_navlinks', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_additional_navlinks\', \'\')') or error('Unable to insert config value \'o_additional_navlinks\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_topic_views
- if (!array_key_exists('o_topic_views', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_topic_views\', \'1\')') or error('Unable to insert config value \'o_topic_views\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_signatures
- if (!array_key_exists('o_signatures', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_signatures\', \'1\')') or error('Unable to insert config value \'o_signatures\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_smtp_ssl
- if (!array_key_exists('o_smtp_ssl', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_smtp_ssl\', \'0\')') or error('Unable to insert config value \'o_smtp_ssl\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_default_dst
- if (!array_key_exists('o_default_dst', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_default_dst\', \'0\')') or error('Unable to insert config value \'o_default_dst\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_quote_depth
- if (!array_key_exists('o_quote_depth', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_quote_depth\', \'3\')') or error('Unable to insert config value \'o_quote_depth\'', __FILE__, __LINE__, $db->error());
-
- // Insert new config option o_feed_type
- if (!array_key_exists('o_feed_type', $pun_config))
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_feed_type\', \'2\')') or error('Unable to insert config value \'o_feed_type\'', __FILE__, __LINE__, $db->error());
-
- // Insert config option o_base_url which was removed in 1.3
- if (!array_key_exists('o_base_url', $pun_config))
- {
- // If it isn't in $pun_config['o_base_url'] it should be in $base_url, but just in-case it isn't we can make a guess at it
- if (!isset($base_url))
- {
- // Make an educated guess regarding base_url
- $base_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; // protocol
- $base_url .= preg_replace('/:(80|443)$/', '', $_SERVER['HTTP_HOST']); // host[:port]
- $base_url .= str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])); // path
- }
-
- if (substr($base_url, -1) == '/')
- $base_url = substr($base_url, 0, -1);
-
- $db->query('INSERT INTO '.$db->prefix.'config (conf_name, conf_value) VALUES (\'o_base_url\', \''.$db->escape($base_url).'\')') or error('Unable to insert config value \'o_quote_depth\'', __FILE__, __LINE__, $db->error());
- }
-
- if (strpos($cur_version, '1.2') === 0)
- {
- // Groups are almost the same as 1.2:
- // unverified: 32000 -> 0
-
- $db->query('UPDATE '.$db->prefix.'users SET group_id = 0 WHERE group_id = 32000') or error('Unable to update unverified users', __FILE__, __LINE__, $db->error());
- }
- else if (strpos($cur_version, '1.3') === 0)
- {
- // Groups have changed quite a lot from 1.3:
- // unverified: 0 -> 0
- // admin: 1 -> 1
- // mod: ? -> 2
- // guest: 2 -> 3
- // member: ? -> 4
-
- $result = $db->query('SELECT MAX(g_id) + 1 FROM '.$db->prefix.'groups') or error('Unable to select temp group ID', __FILE__, __LINE__, $db->error());
- $temp_id = $db->result($result);
-
- $result = $db->query('SELECT g_id FROM '.$db->prefix.'groups WHERE g_moderator = 1 AND g_id > 1 LIMIT 1') or error('Unable to select moderator group', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result))
- $mod_gid = $db->result($result);
- else
- {
- $db->query('INSERT INTO '.$db->prefix.'groups (g_title, g_user_title, g_moderator, g_mod_edit_users, g_mod_rename_users, g_mod_change_passwords, g_mod_ban_users, g_read_board, g_view_users, g_post_replies, g_post_topics, g_edit_posts, g_delete_posts, g_delete_topics, g_set_title, g_search, g_search_users, g_send_email, g_post_flood, g_search_flood, g_email_flood) VALUES('."'Moderators', 'Moderator', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0)") or error('Unable to add group', __FILE__, __LINE__, $db->error());
- $mod_gid = $db->insert_id();
- }
-
- $member_gid = $pun_config['o_default_user_group'];
-
- // move the mod group to a temp place
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = '.$temp_id.' WHERE g_id = '.$mod_gid) or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = '.$temp_id.' WHERE group_id = '.$mod_gid) or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = '.$temp_id.' WHERE group_id = '.$mod_gid) or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
- if ($member_gid == $mod_gid) $member_gid = $temp_id;
-
- // move whoever is in 3 to a spare slot
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = '.$mod_gid.' WHERE g_id = 3') or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = '.$mod_gid.' WHERE group_id = 3') or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = '.$mod_gid.' WHERE group_id = 3') or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
- if ($member_gid == 3) $member_gid = $mod_gid;
-
- // move guest to 3
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = 3 WHERE g_id = 2') or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = 3 WHERE group_id = 2') or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = 3 WHERE group_id = 2') or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
- if ($member_gid == 2) $member_gid = 3;
-
- // move mod group in temp place to 2
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = 2 WHERE g_id = '.$temp_id) or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = 2 WHERE group_id = '.$temp_id) or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = 2 WHERE group_id = '.$temp_id) or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
- if ($member_gid == $temp_id) $member_gid = 2;
-
- // Only move stuff around if it isn't already in the right place
- if ($member_gid != $mod_gid || $member_gid != 4)
- {
- // move members to temp place
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = '.$temp_id.' WHERE g_id = '.$member_gid) or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = '.$temp_id.' WHERE group_id = '.$member_gid) or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = '.$temp_id.' WHERE group_id = '.$member_gid) or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
-
- // move whoever is in 4 to members place
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = '.$member_gid.' WHERE g_id = 4') or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = '.$member_gid.' WHERE group_id = 4') or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = '.$member_gid.' WHERE group_id = 4') or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
-
- // move members in temp place to 4
- $db->query('UPDATE '.$db->prefix.'groups SET g_id = 4 WHERE g_id = '.$temp_id) or error('Unable to update group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'users SET group_id = 4 WHERE group_id = '.$temp_id) or error('Unable to update users group ID', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'forum_perms SET group_id = 4 WHERE group_id = '.$temp_id) or error('Unable to forum_perms group ID', __FILE__, __LINE__, $db->error());
- }
- }
-
- // Server time zone is now simply the default time zone
- if (!array_key_exists('o_default_timezone', $pun_config))
- $db->query('UPDATE '.$db->prefix.'config SET conf_name = \'o_default_timezone\' WHERE conf_name = \'o_server_timezone\'') or error('Unable to update time zone config', __FILE__, __LINE__, $db->error());
-
- // Increase visit timeout to 30 minutes (only if it hasn't been changed from the default)
- if (!array_key_exists('o_database_revision', $pun_config) && $pun_config['o_timeout_visit'] == '600')
- $db->query('UPDATE '.$db->prefix.'config SET conf_value = \'1800\' WHERE conf_name = \'o_timeout_visit\'') or error('Unable to update visit timeout config', __FILE__, __LINE__, $db->error());
-
- // Remove obsolete g_post_polls permission from groups table
- $db->drop_field('groups', 'g_post_polls');
-
- // Make room for multiple moderator groups
- if (!$db->field_exists('groups', 'g_moderator'))
- {
- // Add g_moderator column to groups table
- $db->add_field('groups', 'g_moderator', 'TINYINT(1)', false, 0, 'g_user_title') or error('Unable to add g_moderator field', __FILE__, __LINE__, $db->error());
-
- // Give the moderator group moderator privileges
- $db->query('UPDATE '.$db->prefix.'groups SET g_moderator = 1 WHERE g_id = 2') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
- }
-
- // Replace obsolete p_mod_edit_users config setting with new per-group permission
- if (array_key_exists('p_mod_edit_users', $pun_config))
- {
- $db->query('DELETE FROM '.$db->prefix.'config WHERE conf_name = \'p_mod_edit_users\'') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
-
- $db->add_field('groups', 'g_mod_edit_users', 'TINYINT(1)', false, 0, 'g_moderator') or error('Unable to add g_mod_edit_users field', __FILE__, __LINE__, $db->error());
-
- $db->query('UPDATE '.$db->prefix.'groups SET g_mod_edit_users = '.$pun_config['p_mod_edit_users'].' WHERE g_moderator = 1') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
- }
-
- // Replace obsolete p_mod_rename_users config setting with new per-group permission
- if (array_key_exists('p_mod_rename_users', $pun_config))
- {
- $db->query('DELETE FROM '.$db->prefix.'config WHERE conf_name = \'p_mod_rename_users\'') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
-
- $db->add_field('groups', 'g_mod_rename_users', 'TINYINT(1)', false, 0, 'g_mod_edit_users') or error('Unable to add g_mod_rename_users field', __FILE__, __LINE__, $db->error());
-
- $db->query('UPDATE '.$db->prefix.'groups SET g_mod_rename_users = '.$pun_config['p_mod_rename_users'].' WHERE g_moderator = 1') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
- }
-
- // Replace obsolete p_mod_change_passwords config setting with new per-group permission
- if (array_key_exists('p_mod_change_passwords', $pun_config))
- {
- $db->query('DELETE FROM '.$db->prefix.'config WHERE conf_name = \'p_mod_change_passwords\'') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
-
- $db->add_field('groups', 'g_mod_change_passwords', 'TINYINT(1)', false, 0, 'g_mod_rename_users') or error('Unable to add g_mod_change_passwords field', __FILE__, __LINE__, $db->error());
-
- $db->query('UPDATE '.$db->prefix.'groups SET g_mod_change_passwords = '.$pun_config['p_mod_change_passwords'].' WHERE g_moderator = 1') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
- }
-
- // Replace obsolete p_mod_ban_users config setting with new per-group permission
- if (array_key_exists('p_mod_ban_users', $pun_config))
- {
- $db->query('DELETE FROM '.$db->prefix.'config WHERE conf_name = \'p_mod_ban_users\'') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
-
- $db->add_field('groups', 'g_mod_ban_users', 'TINYINT(1)', false, 0, 'g_mod_change_passwords') or error('Unable to add g_mod_ban_users field', __FILE__, __LINE__, $db->error());
-
- $db->query('UPDATE '.$db->prefix.'groups SET g_mod_ban_users = '.$pun_config['p_mod_ban_users'].' WHERE g_moderator = 1') or error('Unable to update moderator powers', __FILE__, __LINE__, $db->error());
- }
-
- // We need to add a unique index to avoid users having multiple rows in the online table
- if (!$db->index_exists('online', 'user_id_ident_idx'))
- {
- $db->truncate_table('online') or error('Unable to clear online table', __FILE__, __LINE__, $db->error());
-
- if ($mysql)
- $db->add_index('online', 'user_id_ident_idx', array('user_id', 'ident(25)'), true) or error('Unable to add user_id_ident_idx index', __FILE__, __LINE__, $db->error());
- else
- $db->add_index('online', 'user_id_ident_idx', array('user_id', 'ident'), true) or error('Unable to add user_id_ident_idx index', __FILE__, __LINE__, $db->error());
- }
-
- // Remove the redundant user_id_idx on the online table
- $db->drop_index('online', 'user_id_idx') or error('Unable to drop user_id_idx index', __FILE__, __LINE__, $db->error());
-
- // Add an index to ident on the online table
- if ($mysql)
- $db->add_index('online', 'ident_idx', array('ident(25)')) or error('Unable to add ident_idx index', __FILE__, __LINE__, $db->error());
- else
- $db->add_index('online', 'ident_idx', array('ident')) or error('Unable to add ident_idx index', __FILE__, __LINE__, $db->error());
-
- // Add an index to logged in the online table
- $db->add_index('online', 'logged_idx', array('logged')) or error('Unable to add logged_idx index', __FILE__, __LINE__, $db->error());
-
- // Add an index to last_post in the topics table
- $db->add_index('topics', 'last_post_idx', array('last_post')) or error('Unable to add last_post_idx index', __FILE__, __LINE__, $db->error());
-
- // Add an index to username on the bans table
- if ($mysql)
- $db->add_index('bans', 'username_idx', array('username(25)')) or error('Unable to add username_idx index', __FILE__, __LINE__, $db->error());
- else
- $db->add_index('bans', 'username_idx', array('username')) or error('Unable to add username_idx index', __FILE__, __LINE__, $db->error());
-
- // Change the username_idx on users to a unique index of max size 25
- $db->drop_index('users', 'username_idx') or error('Unable to drop old username_idx index', __FILE__, __LINE__, $db->error());
- $field = $mysql ? 'username(25)' : 'username';
-
- // Attempt to add a unique index. If the user doesn't use a transactional database this can fail due to multiple matching usernames in the
- // users table. This is bad, but just giving up if it happens is even worse! If it fails just add a regular non-unique index.
- if (!$db->add_index('users', 'username_idx', array($field), true))
- $db->add_index('users', 'username_idx', array($field)) or error('Unable to add username_idx field', __FILE__, __LINE__, $db->error());
-
- // Add g_view_users field to groups table
- $db->add_field('groups', 'g_view_users', 'TINYINT(1)', false, 1, 'g_read_board') or error('Unable to add g_view_users field', __FILE__, __LINE__, $db->error());
-
- // Add the last_email_sent column to the users table and the g_send_email and
- // g_email_flood columns to the groups table
- $db->add_field('users', 'last_email_sent', 'INT(10) UNSIGNED', true, null, 'last_search') or error('Unable to add last_email_sent field', __FILE__, __LINE__, $db->error());
- $db->add_field('groups', 'g_send_email', 'TINYINT(1)', false, 1, 'g_search_users') or error('Unable to add g_send_email field', __FILE__, __LINE__, $db->error());
- $db->add_field('groups', 'g_email_flood', 'SMALLINT(6)', false, 60, 'g_search_flood') or error('Unable to add g_email_flood field', __FILE__, __LINE__, $db->error());
-
- // Set non-default g_send_email and g_flood_email values properly
- $db->query('UPDATE '.$db->prefix.'groups SET g_send_email = 0 WHERE g_id = 3') or error('Unable to update group email permissions', __FILE__, __LINE__, $db->error());
- $db->query('UPDATE '.$db->prefix.'groups SET g_email_flood = 0 WHERE g_id IN (1,2,3)') or error('Unable to update group email permissions', __FILE__, __LINE__, $db->error());
-
- // Add the auto notify/subscription option to the users table
- $db->add_field('users', 'auto_notify', 'TINYINT(1)', false, 0, 'notify_with_post') or error('Unable to add auto_notify field', __FILE__, __LINE__, $db->error());
-
- // Add the first_post_id column to the topics table
- if (!$db->field_exists('topics', 'first_post_id'))
- {
- $db->add_field('topics', 'first_post_id', 'INT(10) UNSIGNED', false, 0, 'posted') or error('Unable to add first_post_id field', __FILE__, __LINE__, $db->error());
- $db->add_index('topics', 'first_post_id_idx', array('first_post_id')) or error('Unable to add first_post_id_idx index', __FILE__, __LINE__, $db->error());
-
- // Now that we've added the column and indexed it, we need to give it correct data
- $result = $db->query('SELECT MIN(id) AS first_post, topic_id FROM '.$db->prefix.'posts GROUP BY topic_id') or error('Unable to fetch first_post_id', __FILE__, __LINE__, $db->error());
-
- while ($cur_post = $db->fetch_assoc($result))
- $db->query('UPDATE '.$db->prefix.'topics SET first_post_id = '.$cur_post['first_post'].' WHERE id = '.$cur_post['topic_id']) or error('Unable to update first_post_id', __FILE__, __LINE__, $db->error());
- }
-
- // Move any users with the old unverified status to their new group
- $db->query('UPDATE '.$db->prefix.'users SET group_id=0 WHERE group_id=32000') or error('Unable to move unverified users', __FILE__, __LINE__, $db->error());
-
- // Add the ban_creator column to the bans table
- $db->add_field('bans', 'ban_creator', 'INT(10) UNSIGNED', false, 0) or error('Unable to add ban_creator field', __FILE__, __LINE__, $db->error());
-
- // Add the time/date format settings to the user table
- $db->add_field('users', 'time_format', 'TINYINT(1)', false, 0, 'dst') or error('Unable to add time_format field', __FILE__, __LINE__, $db->error());
- $db->add_field('users', 'date_format', 'TINYINT(1)', false, 0, 'dst') or error('Unable to add date_format field', __FILE__, __LINE__, $db->error());
-
- // Change the search_data field to mediumtext
- $db->alter_field('search_cache', 'search_data', 'MEDIUMTEXT', true) or error('Unable to alter search_data field', __FILE__, __LINE__, $db->error());
-
- // Incase we had the fulltext search extension installed (1.3-legacy), remove it
- $db->drop_index('topics', 'subject_idx') or error('Unable to drop subject_idx index', __FILE__, __LINE__, $db->error());
- $db->drop_index('posts', 'message_idx') or error('Unable to drop message_idx index', __FILE__, __LINE__, $db->error());
-
- // If the search_cache table has been dropped by the fulltext search extension, recreate it
- if (!$db->table_exists('search_cache'))
- {
- $schema = array(
- 'FIELDS' => array(
- 'id' => array(
- 'datatype' => 'INT(10) UNSIGNED',
- 'allow_null' => false,
- 'default' => '0'
- ),
- 'ident' => array(
- 'datatype' => 'VARCHAR(200)',
- 'allow_null' => false,
- 'default' => '\'\''
- ),
- 'search_data' => array(
- 'datatype' => 'MEDIUMTEXT',
- 'allow_null' => true
- )
- ),
- 'PRIMARY KEY' => array('id'),
- 'INDEXES' => array(
- 'ident_idx' => array('ident')
- )
- );
-
- if ($db_type == 'mysql' || $db_type == 'mysqli' || $db_type == 'mysql_innodb' || $db_type == 'mysqli_innodb')
- $schema['INDEXES']['ident_idx'] = array('ident(8)');
-
- $db->create_table('search_cache', $schema);
- }
-
- // If the search_matches table has been dropped by the fulltext search extension, recreate it
- if (!$db->table_exists('search_matches'))
- {
- $schema = array(
- 'FIELDS' => array(
- 'post_id' => array(
- 'datatype' => 'INT(10) UNSIGNED',
- 'allow_null' => false,
- 'default' => '0'
- ),
- 'word_id' => array(
- 'datatype' => 'INT(10) UNSIGNED',
- 'allow_null' => false,
- 'default' => '0'
- ),
- 'subject_match' => array(
- 'datatype' => 'TINYINT(1)',
- 'allow_null' => false,
- 'default' => '0'
- )
- ),
- 'INDEXES' => array(
- 'word_id_idx' => array('word_id'),
- 'post_id_idx' => array('post_id')
- )
- );
-
- $db->create_table('search_matches', $schema);
- }
-
- // If the search_words table has been dropped by the fulltext search extension, recreate it
- if (!$db->table_exists('search_words'))
- {
- $schema = array(
- 'FIELDS' => array(
- 'id' => array(
- 'datatype' => 'SERIAL',
- 'allow_null' => false
- ),
- 'word' => array(
- 'datatype' => 'VARCHAR(20)',
- 'allow_null' => false,
- 'default' => '\'\'',
- 'collation' => 'bin'
- )
- ),
- 'PRIMARY KEY' => array('word'),
- 'INDEXES' => array(
- 'id_idx' => array('id')
- )
- );
-
- if ($db_type == 'sqlite')
- {
- $schema['PRIMARY KEY'] = array('id');
- $schema['UNIQUE KEYS'] = array('word_idx' => array('word'));
- }
-
- $db->create_table('search_words', $schema);
- }
-
- // Change the default style if the old doesn't exist anymore
- if ($pun_config['o_default_style'] != $default_style)
- $db->query('UPDATE '.$db->prefix.'config SET conf_value = \''.$db->escape($default_style).'\' WHERE conf_name = \'o_default_style\'') or error('Unable to update default style config', __FILE__, __LINE__, $db->error());
-
- // Should we do charset conversion or not?
- if (strpos($cur_version, '1.2') === 0 && isset($_GET['convert_charset']))
- $query_str = '?stage=conv_bans&req_old_charset='.$old_charset;
-
- break;
-
-
- // Convert bans
- case 'conv_bans':
- $query_str = '?stage=conv_categories&req_old_charset='.$old_charset;
-
- function _conv_bans($cur_item, $old_charset)
- {
- echo 'Converting ban '.$cur_item['id'].' … '."\n";
-
- convert_to_utf8($cur_item['username'], $old_charset);
- convert_to_utf8($cur_item['message'], $old_charset);
-
- return $cur_item;
- }
-
- $end_at = convert_table_utf8($db->prefix.'bans', '_conv_bans', $old_charset, 'id', $start_at);
-
- if ($end_at !== true)
- $query_str = '?stage=conv_bans&req_old_charset='.$old_charset.'&start_at='.$end_at;
-
- break;
-
-
- // Convert categories
- case 'conv_categories':
- $query_str = '?stage=conv_censors&req_old_charset='.$old_charset;
-
- echo 'Converting categories …'." \n";
-
- function _conv_categories($cur_item, $old_charset)
- {
- convert_to_utf8($cur_item['cat_name'], $old_charset);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'categories', '_conv_categories', $old_charset, 'id');
-
- break;
-
-
- // Convert censor words
- case 'conv_censors':
- $query_str = '?stage=conv_config&req_old_charset='.$old_charset;
-
- echo 'Converting censor words …'." \n";
-
- function _conv_censoring($cur_item, $old_charset)
- {
- convert_to_utf8($cur_item['search_for'], $old_charset);
- convert_to_utf8($cur_item['replace_with'], $old_charset);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'censoring', '_conv_censoring', $old_charset, 'id');
-
- break;
-
-
- // Convert config
- case 'conv_config':
- $query_str = '?stage=conv_forums&req_old_charset='.$old_charset;
-
- echo 'Converting configuration …'." \n";
-
- function _conv_config($cur_item, $old_charset)
- {
- convert_to_utf8($cur_item['conf_value'], $old_charset);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'config', '_conv_config', $old_charset, 'conf_name');
-
- break;
-
-
- // Convert forums
- case 'conv_forums':
- $query_str = '?stage=conv_perms&req_old_charset='.$old_charset;
-
- echo 'Converting forums …'." \n";
-
- function _conv_forums($cur_item, $old_charset)
- {
- $moderators = ($cur_item['moderators'] != '') ? unserialize($cur_item['moderators']) : array();
- $moderators_utf8 = array();
- foreach ($moderators as $mod_username => $mod_user_id)
- {
- convert_to_utf8($mod_username, $old_charset);
- $moderators_utf8[$mod_username] = $mod_user_id;
- }
-
- convert_to_utf8($cur_item['forum_name'], $old_charset);
- convert_to_utf8($cur_item['forum_desc'], $old_charset);
-
- if (!empty($moderators_utf8))
- $cur_item['moderators'] = serialize($moderators_utf8);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'forums', '_conv_forums', $old_charset, 'id');
-
- break;
-
-
- // Convert forum permissions
- case 'conv_perms':
- $query_str = '?stage=conv_groups&req_old_charset='.$old_charset;
-
- alter_table_utf8($db->prefix.'forum_perms');
-
- break;
-
-
- // Convert groups
- case 'conv_groups':
- $query_str = '?stage=conv_online&req_old_charset='.$old_charset;
-
- echo 'Converting groups …'." \n";
-
- function _conv_groups($cur_item, $old_charset)
- {
- convert_to_utf8($cur_item['g_title'], $old_charset);
- convert_to_utf8($cur_item['g_user_title'], $old_charset);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'groups', '_conv_groups', $old_charset, 'g_id');
-
- break;
-
-
- // Convert online
- case 'conv_online':
- $query_str = '?stage=conv_posts&req_old_charset='.$old_charset;
-
- // Truncate the table
- $db->truncate_table('online') or error('Unable to empty online table', __FILE__, __LINE__, $db->error());
-
- alter_table_utf8($db->prefix.'online');
-
- break;
-
-
- // Convert posts
- case 'conv_posts':
- $query_str = '?stage=conv_ranks&req_old_charset='.$old_charset;
-
- function _conv_posts($cur_item, $old_charset)
- {
- echo 'Converting post '.$cur_item['id'].' … '."\n";
-
- convert_to_utf8($cur_item['poster'], $old_charset);
- convert_to_utf8($cur_item['message'], $old_charset);
- convert_to_utf8($cur_item['edited_by'], $old_charset);
-
- return $cur_item;
- }
-
- $end_at = convert_table_utf8($db->prefix.'posts', '_conv_posts', $old_charset, 'id', $start_at);
-
- if ($end_at !== true)
- $query_str = '?stage=conv_posts&req_old_charset='.$old_charset.'&start_at='.$end_at;
-
- break;
-
-
- // Convert ranks
- case 'conv_ranks':
- $query_str = '?stage=conv_reports&req_old_charset='.$old_charset;
-
- echo 'Converting ranks …'." \n";
-
- function _conv_ranks($cur_item, $old_charset)
- {
- convert_to_utf8($cur_item['rank'], $old_charset);
-
- return $cur_item;
- }
-
- convert_table_utf8($db->prefix.'ranks', '_conv_ranks', $old_charset, 'id');
-
- break;
-
-
- // Convert reports
- case 'conv_reports':
- $query_str = '?stage=conv_search_cache&req_old_charset='.$old_charset;
-
- function _conv_reports($cur_item, $old_charset)
- {
- echo 'Converting report '.$cur_item['id'].' … '."\n";
-
- convert_to_utf8($cur_item['message'], $old_charset);
-
- return $cur_item;
- }
-
- $end_at = convert_table_utf8($db->prefix.'reports', '_conv_reports', $old_charset, 'id', $start_at);
-
- if ($end_at !== true)
- $query_str = '?stage=conv_reports&req_old_charset='.$old_charset.'&start_at='.$end_at;
-
- break;
-
-
- // Convert search cache
- case 'conv_search_cache':
- $query_str = '?stage=conv_search_matches&req_old_charset='.$old_charset;
-
- // Truncate the table
- $db->truncate_table('search_cache') or error('Unable to empty search cache table', __FILE__, __LINE__, $db->error());
-
- alter_table_utf8($db->prefix.'search_cache');
-
- break;
-
-
- // Convert search matches
- case 'conv_search_matches':
- $query_str = '?stage=conv_search_words&req_old_charset='.$old_charset;
-
- // Truncate the table
- $db->truncate_table('search_matches') or error('Unable to empty search index match table', __FILE__, __LINE__, $db->error());
-
- alter_table_utf8($db->prefix.'search_matches');
-
- break;
-
-
- // Convert search words
- case 'conv_search_words':
- $query_str = '?stage=conv_subscriptions&req_old_charset='.$old_charset;
-
- // Truncate the table
- $db->truncate_table('search_words') or error('Unable to empty search index words table', __FILE__, __LINE__, $db->error());
-
- // Reset the sequence for the search words (not needed for SQLite)
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- $db->query('ALTER TABLE '.$db->prefix.'search_words auto_increment=1') or error('Unable to update table auto_increment', __FILE__, __LINE__, $db->error());
- break;
-
- case 'pgsql';
- $db->query('SELECT setval(\''.$db->prefix.'search_words_id_seq\', 1, false)') or error('Unable to update sequence', __FILE__, __LINE__, $db->error());
- break;
- }
-
- alter_table_utf8($db->prefix.'search_words');
-
- break;
-
-
- // Convert subscriptions
- case 'conv_subscriptions':
- $query_str = '?stage=conv_topics&req_old_charset='.$old_charset;
-
- alter_table_utf8($db->prefix.'subscriptions');
-
- break;
-
-
- // Convert topics
- case 'conv_topics':
- $query_str = '?stage=conv_users&req_old_charset='.$old_charset;
-
- function _conv_topics($cur_item, $old_charset)
- {
- echo 'Converting topic '.$cur_item['id'].' … '."\n";
-
- convert_to_utf8($cur_item['poster'], $old_charset);
- convert_to_utf8($cur_item['subject'], $old_charset);
- convert_to_utf8($cur_item['last_poster'], $old_charset);
-
- return $cur_item;
- }
-
- $end_at = convert_table_utf8($db->prefix.'topics', '_conv_topics', $old_charset, 'id', $start_at);
-
- if ($end_at !== true)
- $query_str = '?stage=conv_topics&req_old_charset='.$old_charset.'&start_at='.$end_at;
-
- break;
-
-
- // Convert users
- case 'conv_users':
- $query_str = '?stage=preparse_posts';
-
- function _conv_users($cur_item, $old_charset)
- {
- echo 'Converting user '.$cur_item['id'].' … '."\n";
-
- convert_to_utf8($cur_item['username'], $old_charset);
- convert_to_utf8($cur_item['title'], $old_charset);
- convert_to_utf8($cur_item['realname'], $old_charset);
- convert_to_utf8($cur_item['location'], $old_charset);
- convert_to_utf8($cur_item['signature'], $old_charset);
- convert_to_utf8($cur_item['admin_note'], $old_charset);
-
- return $cur_item;
- }
-
- $end_at = convert_table_utf8($db->prefix.'users', '_conv_users', $old_charset, 'id', $start_at);
-
- if ($end_at !== true)
- $query_str = '?stage=conv_users&req_old_charset='.$old_charset.'&start_at='.$end_at;
-
- break;
-
-
- // Check if we need to do any more work
- case 'pre_finish':
- $query_str = '?stage=finish';
-
- // If we are doing a major update we should preparse the posts and reindex everything
- if (strpos($cur_version, substr(UPDATE_TO, 0, 3)) !== 0)
- $query_str = '?stage=preparse_posts';
-
- break;
-
-
- // Preparse posts
- case 'preparse_posts':
- $query_str = '?stage=preparse_sigs';
-
- require PUN_ROOT.'include/parser.php';
-
- // Fetch posts to process this cycle
- $result = $db->query('SELECT id, message FROM '.$db->prefix.'posts WHERE id > '.$start_at.' ORDER BY id ASC LIMIT '.PER_PAGE) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
-
- $temp = array();
- $end_at = 0;
- while ($cur_item = $db->fetch_assoc($result))
- {
- echo 'Preparsing post '.$cur_item['id'].' … '."\n";
- $db->query('UPDATE '.$db->prefix.'posts SET message = \''.$db->escape(preparse_bbcode($cur_item['message'], $temp)).'\' WHERE id = '.$cur_item['id']) or error('Unable to update post', __FILE__, __LINE__, $db->error());
-
- $end_at = $cur_item['id'];
- }
-
- // Check if there is more work to do
- if ($end_at > 0)
- {
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE id > '.$end_at.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch next ID', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result) > 0)
- $query_str = '?stage=preparse_posts&start_at='.$end_at;
- }
-
- break;
-
-
- // Preparse signatures
- case 'preparse_sigs':
- $query_str = '?stage=rebuild_idx';
-
- require PUN_ROOT.'include/parser.php';
-
- // Fetch users to process this cycle
- $result = $db->query('SELECT id, signature FROM '.$db->prefix.'users WHERE id > '.$start_at.' ORDER BY id ASC LIMIT '.PER_PAGE) or error('Unable to fetch users', __FILE__, __LINE__, $db->error());
-
- $temp = array();
- $end_at = 0;
- while ($cur_item = $db->fetch_assoc($result))
- {
- echo 'Preparsing signature '.$cur_item['id'].' … '."\n";
- $db->query('UPDATE '.$db->prefix.'users SET signature = \''.$db->escape(preparse_bbcode($cur_item['signature'], $temp, true)).'\' WHERE id = '.$cur_item['id']) or error('Unable to update user', __FILE__, __LINE__, $db->error());
-
- $end_at = $cur_item['id'];
- }
-
- // Check if there is more work to do
- if ($end_at > 0)
- {
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'users WHERE id > '.$end_at.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch next ID', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result) > 0)
- $query_str = '?stage=preparse_sigs&start_at='.$end_at;
- }
-
- break;
-
-
- // Rebuild the search index
- case 'rebuild_idx':
- $query_str = '?stage=finish';
-
- if ($start_at == 0)
- {
- // Truncate the tables just in-case we didn't already (if we are coming directly here without converting the tables)
- $db->truncate_table('search_cache') or error('Unable to empty search cache table', __FILE__, __LINE__, $db->error());
- $db->truncate_table('search_matches') or error('Unable to empty search index match table', __FILE__, __LINE__, $db->error());
- $db->truncate_table('search_words') or error('Unable to empty search index words table', __FILE__, __LINE__, $db->error());
-
- // Reset the sequence for the search words (not needed for SQLite)
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- $db->query('ALTER TABLE '.$db->prefix.'search_words auto_increment=1') or error('Unable to update table auto_increment', __FILE__, __LINE__, $db->error());
- break;
-
- case 'pgsql';
- $db->query('SELECT setval(\''.$db->prefix.'search_words_id_seq\', 1, false)') or error('Unable to update sequence', __FILE__, __LINE__, $db->error());
- break;
- }
- }
-
- require PUN_ROOT.'include/search_idx.php';
-
- // Fetch posts to process this cycle
- $result = $db->query('SELECT p.id, p.message, t.subject, t.first_post_id FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'topics AS t ON t.id=p.topic_id WHERE p.id > '.$start_at.' ORDER BY p.id ASC LIMIT '.PER_PAGE) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
-
- $end_at = 0;
- while ($cur_item = $db->fetch_assoc($result))
- {
- echo 'Rebuilding index for post '.$cur_item['id'].' … '."\n";
-
- if ($cur_item['id'] == $cur_item['first_post_id'])
- update_search_index('post', $cur_item['id'], $cur_item['message'], $cur_item['subject']);
- else
- update_search_index('post', $cur_item['id'], $cur_item['message']);
-
- $end_at = $cur_item['id'];
- }
-
- // Check if there is more work to do
- if ($end_at > 0)
- {
- $result = $db->query('SELECT 1 FROM '.$db->prefix.'posts WHERE id > '.$end_at.' ORDER BY id ASC LIMIT 1') or error('Unable to fetch next ID', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result) > 0)
- $query_str = '?stage=rebuild_idx&start_at='.$end_at;
- }
-
- break;
-
-
- // Show results page
- case 'finish':
- // We update the version number
- $db->query('UPDATE '.$db->prefix.'config SET conf_value = \''.UPDATE_TO.'\' WHERE conf_name = \'o_cur_version\'') or error('Unable to update version', __FILE__, __LINE__, $db->error());
-
- // And the database revision number
- $db->query('UPDATE '.$db->prefix.'config SET conf_value = \''.UPDATE_TO_DB_REVISION.'\' WHERE conf_name = \'o_database_revision\'') or error('Unable to update database revision number', __FILE__, __LINE__, $db->error());
-
- // This feels like a good time to synchronize the forums
- $result = $db->query('SELECT id FROM '.$db->prefix.'forums') or error('Unable to fetch forum IDs', __FILE__, __LINE__, $db->error());
-
- while ($row = $db->fetch_row($result))
- update_forum($row[0]);
-
- // Empty the PHP cache
- forum_clear_cache();
-
-?>
-
-
-
-
-
-FluxBB Database Update
-
-
-
-
-
-..
diff --git a/upload/img/index.html b/upload/img/index.html
deleted file mode 100644
index 89337b2..0000000
--- a/upload/img/index.html
+++ /dev/null
@@ -1 +0,0 @@
-..
diff --git a/upload/img/smilies/big_smile.png b/upload/img/smilies/big_smile.png
deleted file mode 100644
index b29719b..0000000
Binary files a/upload/img/smilies/big_smile.png and /dev/null differ
diff --git a/upload/img/smilies/cool.png b/upload/img/smilies/cool.png
deleted file mode 100644
index a875361..0000000
Binary files a/upload/img/smilies/cool.png and /dev/null differ
diff --git a/upload/img/smilies/hmm.png b/upload/img/smilies/hmm.png
deleted file mode 100644
index 69e416a..0000000
Binary files a/upload/img/smilies/hmm.png and /dev/null differ
diff --git a/upload/img/smilies/index.html b/upload/img/smilies/index.html
deleted file mode 100644
index 89337b2..0000000
--- a/upload/img/smilies/index.html
+++ /dev/null
@@ -1 +0,0 @@
-..
diff --git a/upload/img/smilies/lol.png b/upload/img/smilies/lol.png
deleted file mode 100644
index dd9058b..0000000
Binary files a/upload/img/smilies/lol.png and /dev/null differ
diff --git a/upload/img/smilies/mad.png b/upload/img/smilies/mad.png
deleted file mode 100644
index 011079d..0000000
Binary files a/upload/img/smilies/mad.png and /dev/null differ
diff --git a/upload/img/smilies/neutral.png b/upload/img/smilies/neutral.png
deleted file mode 100644
index 9bc5ca0..0000000
Binary files a/upload/img/smilies/neutral.png and /dev/null differ
diff --git a/upload/img/smilies/roll.png b/upload/img/smilies/roll.png
deleted file mode 100644
index e2e8e2a..0000000
Binary files a/upload/img/smilies/roll.png and /dev/null differ
diff --git a/upload/img/smilies/sad.png b/upload/img/smilies/sad.png
deleted file mode 100644
index c14e144..0000000
Binary files a/upload/img/smilies/sad.png and /dev/null differ
diff --git a/upload/img/smilies/smile.png b/upload/img/smilies/smile.png
deleted file mode 100644
index 44cc239..0000000
Binary files a/upload/img/smilies/smile.png and /dev/null differ
diff --git a/upload/img/smilies/tongue.png b/upload/img/smilies/tongue.png
deleted file mode 100644
index 5302c89..0000000
Binary files a/upload/img/smilies/tongue.png and /dev/null differ
diff --git a/upload/img/smilies/wink.png b/upload/img/smilies/wink.png
deleted file mode 100644
index 595c1fe..0000000
Binary files a/upload/img/smilies/wink.png and /dev/null differ
diff --git a/upload/img/smilies/yikes.png b/upload/img/smilies/yikes.png
deleted file mode 100644
index bb4aefd..0000000
Binary files a/upload/img/smilies/yikes.png and /dev/null differ
diff --git a/upload/img/test.png b/upload/img/test.png
deleted file mode 100644
index 571ad8e..0000000
Binary files a/upload/img/test.png and /dev/null differ
diff --git a/upload/include/cache.php b/upload/include/cache.php
deleted file mode 100644
index fba95e3..0000000
--- a/upload/include/cache.php
+++ /dev/null
@@ -1,145 +0,0 @@
-query('SELECT * FROM '.$db->prefix.'config', true) or error('Unable to fetch forum config', __FILE__, __LINE__, $db->error());
- while ($cur_config_item = $db->fetch_row($result))
- $output[$cur_config_item[0]] = $cur_config_item[1];
-
- // Output config as PHP code
- $fh = @fopen(FORUM_CACHE_DIR.'cache_config.php', 'wb');
- if (!$fh)
- error('Unable to write configuration cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
-
- fwrite($fh, '');
-
- fclose($fh);
-}
-
-
-//
-// Generate the bans cache PHP script
-//
-function generate_bans_cache()
-{
- global $db;
-
- // Get the ban list from the DB
- $result = $db->query('SELECT * FROM '.$db->prefix.'bans', true) or error('Unable to fetch ban list', __FILE__, __LINE__, $db->error());
-
- $output = array();
- while ($cur_ban = $db->fetch_assoc($result))
- $output[] = $cur_ban;
-
- // Output ban list as PHP code
- $fh = @fopen(FORUM_CACHE_DIR.'cache_bans.php', 'wb');
- if (!$fh)
- error('Unable to write bans cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
-
- fwrite($fh, '');
-
- fclose($fh);
-}
-
-
-//
-// Generate the ranks cache PHP script
-//
-function generate_ranks_cache()
-{
- global $db;
-
- // Get the rank list from the DB
- $result = $db->query('SELECT * FROM '.$db->prefix.'ranks ORDER BY min_posts', true) or error('Unable to fetch rank list', __FILE__, __LINE__, $db->error());
-
- $output = array();
- while ($cur_rank = $db->fetch_assoc($result))
- $output[] = $cur_rank;
-
- // Output ranks list as PHP code
- $fh = @fopen(FORUM_CACHE_DIR.'cache_ranks.php', 'wb');
- if (!$fh)
- error('Unable to write ranks cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
-
- fwrite($fh, '');
-
- fclose($fh);
-}
-
-
-//
-// Generate quick jump cache PHP scripts
-//
-function generate_quickjump_cache($group_id = false)
-{
- global $db, $lang_common, $pun_user;
-
- // If a group_id was supplied, we generate the quick jump cache for that group only
- if ($group_id !== false)
- $groups[0] = $group_id;
- else
- {
- // A group_id was now supplied, so we generate the quick jump cache for all groups
- $result = $db->query('SELECT g_id FROM '.$db->prefix.'groups') or error('Unable to fetch user group list', __FILE__, __LINE__, $db->error());
- $num_groups = $db->num_rows($result);
-
- for ($i = 0; $i < $num_groups; ++$i)
- $groups[] = $db->result($result, $i);
- }
-
- // Loop through the groups in $groups and output the cache for each of them
- while (list(, $group_id) = @each($groups))
- {
- // Output quick jump as PHP code
- $fh = @fopen(FORUM_CACHE_DIR.'cache_quickjump_'.$group_id.'.php', 'wb');
- if (!$fh)
- error('Unable to write quick jump cache file to cache directory. Please make sure PHP has write access to the directory \'cache\'', __FILE__, __LINE__);
-
- $output = '';
- $output .= "\t\t\t\t".'
'."\n\t\t\t\t\t".''."\n\t\t\t\t".'
'."\n";
-
- fwrite($fh, $output);
-
- fclose($fh);
- }
-}
-
-define('FORUM_CACHE_FUNCTIONS_LOADED', true);
diff --git a/upload/include/common.php b/upload/include/common.php
deleted file mode 100644
index 46d990f..0000000
--- a/upload/include/common.php
+++ /dev/null
@@ -1,176 +0,0 @@
-install.php to install FluxBB first.');
-
-// Load the functions script
-require PUN_ROOT.'include/functions.php';
-
-// Load UTF-8 functions
-require PUN_ROOT.'include/utf8/utf8.php';
-
-// Strip out "bad" UTF-8 characters
-forum_remove_bad_characters();
-
-// Reverse the effect of register_globals
-forum_unregister_globals();
-
-// Record the start time (will be used to calculate the generation time for the page)
-$pun_start = get_microtime();
-
-// Make sure PHP reports all errors except E_NOTICE. FluxBB supports E_ALL, but a lot of scripts it may interact with, do not
-error_reporting(E_ALL ^ E_NOTICE);
-
-// Force POSIX locale (to prevent functions such as strtolower() from messing up UTF-8 strings)
-setlocale(LC_CTYPE, 'C');
-
-// Turn off magic_quotes_runtime
-if (get_magic_quotes_runtime())
- set_magic_quotes_runtime(0);
-
-// Strip slashes from GET/POST/COOKIE (if magic_quotes_gpc is enabled)
-if (get_magic_quotes_gpc())
-{
- function stripslashes_array($array)
- {
- return is_array($array) ? array_map('stripslashes_array', $array) : stripslashes($array);
- }
-
- $_GET = stripslashes_array($_GET);
- $_POST = stripslashes_array($_POST);
- $_COOKIE = stripslashes_array($_COOKIE);
- $_REQUEST = stripslashes_array($_REQUEST);
-}
-
-// If a cookie name is not specified in config.php, we use the default (pun_cookie)
-if (empty($cookie_name))
- $cookie_name = 'pun_cookie';
-
-// If the cache directory is not specified, we use the default setting
-if (!defined('FORUM_CACHE_DIR'))
- define('FORUM_CACHE_DIR', PUN_ROOT.'cache/');
-
-// Define a few commonly used constants
-define('PUN_UNVERIFIED', 0);
-define('PUN_ADMIN', 1);
-define('PUN_MOD', 2);
-define('PUN_GUEST', 3);
-define('PUN_MEMBER', 4);
-
-// Load DB abstraction layer and connect
-require PUN_ROOT.'include/dblayer/common_db.php';
-
-// Start a transaction
-$db->start_transaction();
-
-// Load cached config
-if (file_exists(FORUM_CACHE_DIR.'cache_config.php'))
- include FORUM_CACHE_DIR.'cache_config.php';
-
-if (!defined('PUN_CONFIG_LOADED'))
-{
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_config_cache();
- require FORUM_CACHE_DIR.'cache_config.php';
-}
-
-// Verify that we are running the proper database schema revision
-if (!isset($pun_config['o_database_revision']) || $pun_config['o_database_revision'] < FORUM_DB_REVISION || version_compare($pun_config['o_cur_version'], FORUM_VERSION, '<'))
- exit('Your FluxBB database is out-of-date and must be upgraded in order to continue. Please run db_update.php in order to complete the upgrade process.');
-
-// Enable output buffering
-if (!defined('PUN_DISABLE_BUFFERING'))
-{
- // Should we use gzip output compression?
- if ($pun_config['o_gzip'] && extension_loaded('zlib'))
- ob_start('ob_gzhandler');
- else
- ob_start();
-}
-
-// Define standard date/time formats
-$forum_time_formats = array($pun_config['o_time_format'], 'H:i:s', 'H:i', 'g:i:s a', 'g:i a');
-$forum_date_formats = array($pun_config['o_date_format'], 'Y-m-d', 'Y-d-m', 'd-m-Y', 'm-d-Y', 'M j Y', 'jS M Y');
-
-// Check/update/set cookie and fetch user info
-$pun_user = array();
-check_cookie($pun_user);
-
-// Attempt to load the common language file
-if (file_exists(PUN_ROOT.'lang/'.$pun_user['language'].'/common.php'))
- include PUN_ROOT.'lang/'.$pun_user['language'].'/common.php';
-else
- error('There is no valid language pack \''.pun_htmlspecialchars($pun_user['language']).'\' installed. Please reinstall a language of that name');
-
-// Check if we are to display a maintenance message
-if ($pun_config['o_maintenance'] && $pun_user['g_id'] > PUN_ADMIN && !defined('PUN_TURN_OFF_MAINT'))
- maintenance_message();
-
-// Load cached bans
-if (file_exists(FORUM_CACHE_DIR.'cache_bans.php'))
- include FORUM_CACHE_DIR.'cache_bans.php';
-
-if (!defined('PUN_BANS_LOADED'))
-{
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_bans_cache();
- require FORUM_CACHE_DIR.'cache_bans.php';
-}
-
-// Check if current user is banned
-check_bans();
-
-// Update online list
-update_users_online();
-
-// Check to see if we logged in without a cookie being set
-if ($pun_user['is_guest'] && isset($_GET['login']))
- message($lang_common['No cookie']);
-
-if (!defined('PUN_MAX_POSTSIZE'))
- define('PUN_MAX_POSTSIZE', 65535);
-
-if (!defined('PUN_SEARCH_MIN_WORD'))
- define('PUN_SEARCH_MIN_WORD', 3);
-if (!defined('PUN_SEARCH_MAX_WORD'))
- define('PUN_SEARCH_MAX_WORD', 20);
diff --git a/upload/include/common_admin.php b/upload/include/common_admin.php
deleted file mode 100644
index 023b7f3..0000000
--- a/upload/include/common_admin.php
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-query('SELECT id FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id.$extra_sql, true) or error('Unable to fetch topics', __FILE__, __LINE__, $db->error());
-
- $topic_ids = '';
- while ($row = $db->fetch_row($result))
- $topic_ids .= (($topic_ids != '') ? ',' : '').$row[0];
-
- if ($topic_ids != '')
- {
- // Fetch posts to prune
- $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id IN('.$topic_ids.')', true) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
-
- $post_ids = '';
- while ($row = $db->fetch_row($result))
- $post_ids .= (($post_ids != '') ? ',' : '').$row[0];
-
- if ($post_ids != '')
- {
- // Delete topics
- $db->query('DELETE FROM '.$db->prefix.'topics WHERE id IN('.$topic_ids.')') or error('Unable to prune topics', __FILE__, __LINE__, $db->error());
- // Delete subscriptions
- $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id IN('.$topic_ids.')') or error('Unable to prune subscriptions', __FILE__, __LINE__, $db->error());
- // Delete posts
- $db->query('DELETE FROM '.$db->prefix.'posts WHERE id IN('.$post_ids.')') or error('Unable to prune posts', __FILE__, __LINE__, $db->error());
-
- // We removed a bunch of posts, so now we have to update the search index
- require_once PUN_ROOT.'include/search_idx.php';
- strip_search_index($post_ids);
- }
- }
-}
diff --git a/upload/include/dblayer/common_db.php b/upload/include/dblayer/common_db.php
deleted file mode 100644
index 121d895..0000000
--- a/upload/include/dblayer/common_db.php
+++ /dev/null
@@ -1,48 +0,0 @@
-..
diff --git a/upload/include/dblayer/mysql.php b/upload/include/dblayer/mysql.php
deleted file mode 100644
index c595da4..0000000
--- a/upload/include/dblayer/mysql.php
+++ /dev/null
@@ -1,347 +0,0 @@
- 'INT(10) UNSIGNED AUTO_INCREMENT'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- $this->prefix = $db_prefix;
-
- if ($p_connect)
- $this->link_id = @mysql_pconnect($db_host, $db_username, $db_password);
- else
- $this->link_id = @mysql_connect($db_host, $db_username, $db_password);
-
- if ($this->link_id)
- {
- if (!@mysql_select_db($db_name, $this->link_id))
- error('Unable to select database. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
- }
- else
- error('Unable to connect to MySQL server. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
-
- // Setup the client-server character set (UTF-8)
- if (!defined('FORUM_NO_SET_NAMES'))
- $this->set_names('utf8');
-
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- return;
- }
-
-
- function end_transaction()
- {
- return;
- }
-
-
- function query($sql, $unbuffered = false)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- if ($unbuffered)
- $this->query_result = @mysql_unbuffered_query($sql, $this->link_id);
- else
- $this->query_result = @mysql_query($sql, $this->link_id);
-
- if ($this->query_result)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- return ($query_id) ? @mysql_result($query_id, $row, $col) : false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @mysql_fetch_row($query_id) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @mysql_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false;
- }
-
-
- function insert_id()
- {
- return ($this->link_id) ? @mysql_insert_id($this->link_id) : false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- return ($query_id) ? @mysql_free_result($query_id) : false;
- }
-
-
- function escape($str)
- {
- if (is_array($str))
- return '';
- else if (function_exists('mysql_real_escape_string'))
- return mysql_real_escape_string($str, $this->link_id);
- else
- return mysql_escape_string($str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = @mysql_errno($this->link_id);
- $result['error_msg'] = @mysql_error($this->link_id);
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->query_result)
- @mysql_free_result($this->query_result);
-
- return @mysql_close($this->link_id);
- }
- else
- return false;
- }
-
- function set_names($names)
- {
- return $this->query('SET NAMES \''.$this->escape($names).'\'');
- }
-
- function get_version()
- {
- $result = $this->query('SELECT VERSION()');
-
- return array(
- 'name' => 'MySQL Standard',
- 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
- );
- }
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $exists = false;
-
- $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
- while ($cur_index = $this->fetch_assoc($result))
- {
- if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
- {
- $exists = true;
- break;
- }
- }
-
- return $exists;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- if (isset($field_data['collation']))
- $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
-
- if (!$field_data['allow_null'])
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
- }
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'MyISAM').' CHARACTER SET utf8';
-
- return $this->query($query) ? true : false;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/dblayer/mysql_innodb.php b/upload/include/dblayer/mysql_innodb.php
deleted file mode 100644
index b78c63c..0000000
--- a/upload/include/dblayer/mysql_innodb.php
+++ /dev/null
@@ -1,363 +0,0 @@
- 'INT(10) UNSIGNED AUTO_INCREMENT'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- $this->prefix = $db_prefix;
-
- if ($p_connect)
- $this->link_id = @mysql_pconnect($db_host, $db_username, $db_password);
- else
- $this->link_id = @mysql_connect($db_host, $db_username, $db_password);
-
- if ($this->link_id)
- {
- if (!@mysql_select_db($db_name, $this->link_id))
- error('Unable to select database. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
- }
- else
- error('Unable to connect to MySQL server. MySQL reported: '.mysql_error(), __FILE__, __LINE__);
-
- // Setup the client-server character set (UTF-8)
- if (!defined('FORUM_NO_SET_NAMES'))
- $this->set_names('utf8');
-
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- ++$this->in_transaction;
-
- mysql_query('START TRANSACTION', $this->link_id);
- return;
- }
-
-
- function end_transaction()
- {
- --$this->in_transaction;
-
- mysql_query('COMMIT', $this->link_id);
- return;
- }
-
-
- function query($sql, $unbuffered = false)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- if ($unbuffered)
- $this->query_result = @mysql_unbuffered_query($sql, $this->link_id);
- else
- $this->query_result = @mysql_query($sql, $this->link_id);
-
- if ($this->query_result)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- // Rollback transaction
- if ($this->in_transaction)
- mysql_query('ROLLBACK', $this->link_id);
-
- --$this->in_transaction;
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- return ($query_id) ? @mysql_result($query_id, $row, $col) : false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @mysql_fetch_row($query_id) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @mysql_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false;
- }
-
-
- function insert_id()
- {
- return ($this->link_id) ? @mysql_insert_id($this->link_id) : false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- return ($query_id) ? @mysql_free_result($query_id) : false;
- }
-
-
- function escape($str)
- {
- if (is_array($str))
- return '';
- else if (function_exists('mysql_real_escape_string'))
- return mysql_real_escape_string($str, $this->link_id);
- else
- return mysql_escape_string($str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = @mysql_errno($this->link_id);
- $result['error_msg'] = @mysql_error($this->link_id);
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->query_result)
- @mysql_free_result($this->query_result);
-
- return @mysql_close($this->link_id);
- }
- else
- return false;
- }
-
-
- function set_names($names)
- {
- return $this->query('SET NAMES \''.$this->escape($names).'\'');
- }
-
-
- function get_version()
- {
- $result = $this->query('SELECT VERSION()');
-
- return array(
- 'name' => 'MySQL Standard (InnoDB)',
- 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
- );
- }
-
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $exists = false;
-
- $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
- while ($cur_index = $this->fetch_assoc($result))
- {
- if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
- {
- $exists = true;
- break;
- }
- }
-
- return $exists;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- if (isset($field_data['collation']))
- $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
-
- if (!$field_data['allow_null'])
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
- }
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'InnoDB').' CHARACTER SET utf8';
-
- return $this->query($query) ? true : false;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/dblayer/mysqli.php b/upload/include/dblayer/mysqli.php
deleted file mode 100644
index 9b81bdd..0000000
--- a/upload/include/dblayer/mysqli.php
+++ /dev/null
@@ -1,352 +0,0 @@
- 'INT(10) UNSIGNED AUTO_INCREMENT'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- $this->prefix = $db_prefix;
-
- // Was a custom port supplied with $db_host?
- if (strpos($db_host, ':') !== false)
- list($db_host, $db_port) = explode(':', $db_host);
-
- // Persistent connection in MySQLi are only available in PHP 5.3 and later releases
- $p_connect = $p_connect && version_compare(PHP_VERSION, '5.3.0', '>=') ? 'p:' : '';
-
- if (isset($db_port))
- $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name, $db_port);
- else
- $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name);
-
- if (!$this->link_id)
- error('Unable to connect to MySQL and select database. MySQL reported: '.mysqli_connect_error(), __FILE__, __LINE__);
-
- // Setup the client-server character set (UTF-8)
- if (!defined('FORUM_NO_SET_NAMES'))
- $this->set_names('utf8');
-
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- return;
- }
-
-
- function end_transaction()
- {
- return;
- }
-
-
- function query($sql, $unbuffered = false)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- $this->query_result = @mysqli_query($this->link_id, $sql);
-
- if ($this->query_result)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- if ($query_id)
- {
- if ($row)
- @mysqli_data_seek($query_id, $row);
-
- $cur_row = @mysqli_fetch_row($query_id);
- return $cur_row[$col];
- }
- else
- return false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- return ($query_id) ? @mysqli_fetch_assoc($query_id) : false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @mysqli_fetch_row($query_id) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @mysqli_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->link_id) ? @mysqli_affected_rows($this->link_id) : false;
- }
-
-
- function insert_id()
- {
- return ($this->link_id) ? @mysqli_insert_id($this->link_id) : false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- return ($query_id) ? @mysqli_free_result($query_id) : false;
- }
-
-
- function escape($str)
- {
- return is_array($str) ? '' : mysqli_real_escape_string($this->link_id, $str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = @mysqli_errno($this->link_id);
- $result['error_msg'] = @mysqli_error($this->link_id);
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->query_result)
- @mysqli_free_result($this->query_result);
-
- return @mysqli_close($this->link_id);
- }
- else
- return false;
- }
-
- function set_names($names)
- {
- return $this->query('SET NAMES \''.$this->escape($names).'\'');
- }
-
-
- function get_version()
- {
- $result = $this->query('SELECT VERSION()');
-
- return array(
- 'name' => 'MySQL Improved',
- 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
- );
- }
-
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $exists = false;
-
- $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
- while ($cur_index = $this->fetch_assoc($result))
- {
- if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
- {
- $exists = true;
- break;
- }
- }
-
- return $exists;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- if (isset($field_data['collation']))
- $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
-
- if (!$field_data['allow_null'])
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
- }
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'MyISAM').' CHARACTER SET utf8';
-
- return $this->query($query) ? true : false;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/dblayer/mysqli_innodb.php b/upload/include/dblayer/mysqli_innodb.php
deleted file mode 100644
index 2b591cd..0000000
--- a/upload/include/dblayer/mysqli_innodb.php
+++ /dev/null
@@ -1,366 +0,0 @@
- 'INT(10) UNSIGNED AUTO_INCREMENT'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- $this->prefix = $db_prefix;
-
- // Was a custom port supplied with $db_host?
- if (strpos($db_host, ':') !== false)
- list($db_host, $db_port) = explode(':', $db_host);
-
- // Persistent connection in MySQLi are only available in PHP 5.3 and later releases
- $p_connect = $p_connect && version_compare(PHP_VERSION, '5.3.0', '>=') ? 'p:' : '';
-
- if (isset($db_port))
- $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name, $db_port);
- else
- $this->link_id = @mysqli_connect($p_connect.$db_host, $db_username, $db_password, $db_name);
-
- if (!$this->link_id)
- error('Unable to connect to MySQL and select database. MySQL reported: '.mysqli_connect_error(), __FILE__, __LINE__);
-
- // Setup the client-server character set (UTF-8)
- if (!defined('FORUM_NO_SET_NAMES'))
- $this->set_names('utf8');
-
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- ++$this->in_transaction;
-
- mysqli_query($this->link_id, 'START TRANSACTION');
- return;
- }
-
-
- function end_transaction()
- {
- --$this->in_transaction;
-
- mysqli_query($this->link_id, 'COMMIT');
- return;
- }
-
-
- function query($sql, $unbuffered = false)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- $this->query_result = @mysqli_query($this->link_id, $sql);
-
- if ($this->query_result)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- // Rollback transaction
- if ($this->in_transaction)
- mysqli_query($this->link_id, 'ROLLBACK');
-
- --$this->in_transaction;
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- if ($query_id)
- {
- if ($row)
- @mysqli_data_seek($query_id, $row);
-
- $cur_row = @mysqli_fetch_row($query_id);
- return $cur_row[$col];
- }
- else
- return false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- return ($query_id) ? @mysqli_fetch_assoc($query_id) : false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @mysqli_fetch_row($query_id) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @mysqli_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->link_id) ? @mysqli_affected_rows($this->link_id) : false;
- }
-
-
- function insert_id()
- {
- return ($this->link_id) ? @mysqli_insert_id($this->link_id) : false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- return ($query_id) ? @mysqli_free_result($query_id) : false;
- }
-
-
- function escape($str)
- {
- return is_array($str) ? '' : mysqli_real_escape_string($this->link_id, $str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = @mysqli_errno($this->link_id);
- $result['error_msg'] = @mysqli_error($this->link_id);
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->query_result)
- @mysqli_free_result($this->query_result);
-
- return @mysqli_close($this->link_id);
- }
- else
- return false;
- }
-
-
- function set_names($names)
- {
- return $this->query('SET NAMES \''.$this->escape($names).'\'');
- }
-
-
- function get_version()
- {
- $result = $this->query('SELECT VERSION()');
-
- return array(
- 'name' => 'MySQL Improved (InnoDB)',
- 'version' => preg_replace('/^([^-]+).*$/', '\\1', $this->result($result))
- );
- }
-
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SHOW TABLES LIKE \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SHOW COLUMNS FROM '.($no_prefix ? '' : $this->prefix).$table_name.' LIKE \''.$this->escape($field_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $exists = false;
-
- $result = $this->query('SHOW INDEX FROM '.($no_prefix ? '' : $this->prefix).$table_name);
- while ($cur_index = $this->fetch_assoc($result))
- {
- if ($cur_index['Key_name'] == ($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name)
- {
- $exists = true;
- break;
- }
- }
-
- return $exists;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- if (isset($field_data['collation']))
- $query .= 'CHARACTER SET utf8 COLLATE utf8_'.$field_data['collation'];
-
- if (!$field_data['allow_null'])
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$key_name.'('.implode(',', $key_fields).'),'."\n";
- }
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $query .= 'KEY '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.'('.implode(',', $index_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".') ENGINE = '.(isset($schema['ENGINE']) ? $schema['ENGINE'] : 'InnoDB').' CHARACTER SET utf8';
-
- return $this->query($query) ? true : false;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- if ($default_value !== null && !is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' MODIFY '.$field_name.' '.$field_type.($allow_null ? ' ' : ' NOT NULL').($default_value !== null ? ' DEFAULT '.$default_value : ' ').($after_field != null ? ' AFTER '.$after_field : '')) ? true : false;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('TRUNCATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/dblayer/pgsql.php b/upload/include/dblayer/pgsql.php
deleted file mode 100644
index 05d8cf0..0000000
--- a/upload/include/dblayer/pgsql.php
+++ /dev/null
@@ -1,427 +0,0 @@
- 'SMALLINT',
- '/^(MEDIUM)?INT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'INTEGER',
- '/^BIGINT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'BIGINT',
- '/^(TINY|MEDIUM|LONG)?TEXT$/i' => 'TEXT',
- '/^DOUBLE( )?(\\([0-9,]+\\))?( )?(UNSIGNED)?$/i' => 'DOUBLE PRECISION',
- '/^FLOAT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'REAL'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- $this->prefix = $db_prefix;
-
- if ($db_host)
- {
- if (strpos($db_host, ':') !== false)
- {
- list($db_host, $dbport) = explode(':', $db_host);
- $connect_str[] = 'host='.$db_host.' port='.$dbport;
- }
- else
- $connect_str[] = 'host='.$db_host;
- }
-
- if ($db_name)
- $connect_str[] = 'dbname='.$db_name;
-
- if ($db_username)
- $connect_str[] = 'user='.$db_username;
-
- if ($db_password)
- $connect_str[] = 'password='.$db_password;
-
- if ($p_connect)
- $this->link_id = @pg_pconnect(implode(' ', $connect_str));
- else
- $this->link_id = @pg_connect(implode(' ', $connect_str));
-
- if (!$this->link_id)
- error('Unable to connect to PostgreSQL server', __FILE__, __LINE__);
-
- // Setup the client-server character set (UTF-8)
- if (!defined('FORUM_NO_SET_NAMES'))
- $this->set_names('utf8');
-
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- ++$this->in_transaction;
-
- return (@pg_query($this->link_id, 'BEGIN')) ? true : false;
- }
-
-
- function end_transaction()
- {
- --$this->in_transaction;
-
- if (@pg_query($this->link_id, 'COMMIT'))
- return true;
- else
- {
- @pg_query($this->link_id, 'ROLLBACK');
- return false;
- }
- }
-
-
- function query($sql, $unbuffered = false) // $unbuffered is ignored since there is no pgsql_unbuffered_query()
- {
- if (strrpos($sql, 'LIMIT') !== false)
- $sql = preg_replace('#LIMIT ([0-9]+),([ 0-9]+)#', 'LIMIT \\2 OFFSET \\1', $sql);
-
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- @pg_send_query($this->link_id, $sql);
- $this->query_result = @pg_get_result($this->link_id);
-
- if (pg_result_status($this->query_result) != PGSQL_FATAL_ERROR)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- $this->last_query_text[$this->query_result] = $sql;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- $this->error_msg = @pg_result_error($this->query_result);
-
- if ($this->in_transaction)
- @pg_query($this->link_id, 'ROLLBACK');
-
- --$this->in_transaction;
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- return ($query_id) ? @pg_fetch_result($query_id, $row, $col) : false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- return ($query_id) ? @pg_fetch_assoc($query_id) : false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @pg_fetch_row($query_id) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @pg_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->query_result) ? @pg_affected_rows($this->query_result) : false;
- }
-
-
- function insert_id()
- {
- $query_id = $this->query_result;
-
- if ($query_id && $this->last_query_text[$query_id] != '')
- {
- if (preg_match('/^INSERT INTO ([a-z0-9\_\-]+)/is', $this->last_query_text[$query_id], $table_name))
- {
- // Hack (don't ask)
- if (substr($table_name[1], -6) == 'groups')
- $table_name[1] .= '_g';
-
- $temp_q_id = @pg_query($this->link_id, 'SELECT currval(\''.$table_name[1].'_id_seq\')');
- return ($temp_q_id) ? intval(@pg_fetch_result($temp_q_id, 0)) : false;
- }
- }
-
- return false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- if (!$query_id)
- $query_id = $this->query_result;
-
- return ($query_id) ? @pg_free_result($query_id) : false;
- }
-
-
- function escape($str)
- {
- return is_array($str) ? '' : pg_escape_string($str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = false;
-/*
- if (!empty($this->query_result))
- {
- $result['error_msg'] = trim(@pg_result_error($this->query_result));
- if ($result['error_msg'] != '')
- return $result;
- }
-
- $result['error_msg'] = (!empty($this->link_id)) ? trim(@pg_last_error($this->link_id)) : trim(@pg_last_error());
-*/
- $result['error_msg'] = $this->error_msg;
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->in_transaction)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array('COMMIT', 0);
-
- @pg_query($this->link_id, 'COMMIT');
- }
-
- if ($this->query_result)
- @pg_free_result($this->query_result);
-
- return @pg_close($this->link_id);
- }
- else
- return false;
- }
-
- function set_names($names)
- {
- return $this->query('SET NAMES \''.$this->escape($names).'\'');
- }
-
-
- function get_version()
- {
- $result = $this->query('SELECT VERSION()');
-
- return array(
- 'name' => 'PostgreSQL',
- 'version' => preg_replace('/^[^0-9]+([^\s,-]+).*$/', '\\1', $this->result($result))
- );
- }
-
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SELECT 1 FROM pg_class WHERE relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SELECT 1 FROM pg_class c INNER JOIN pg_attribute a ON a.attrelid = c.oid WHERE c.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND a.attname = \''.$this->escape($field_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $result = $this->query('SELECT 1 FROM pg_index i INNER JOIN pg_class c1 ON c1.oid = i.indrelid INNER JOIN pg_class c2 ON c2.oid = i.indexrelid WHERE c1.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND c2.relname = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_'.$this->escape($index_name).'\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- // The SERIAL datatype is a special case where we don't need to say not null
- if (!$field_data['allow_null'] && $field_data['datatype'] != 'SERIAL')
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE ('.implode(',', $key_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".')';
-
- $result = $this->query($query) ? true : false;
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $result &= $this->add_index($table_name, $index_name, $index_fields, false, $no_prefix);
- }
-
- return $result;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- $result = $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ADD '.$field_name.' '.$field_type) ? true : false;
-
- if ($default_value !== null)
- {
- if (!is_int($default_value) && !is_float($default_value))
- $default_value = '\''.$this->escape($default_value).'\'';
-
- $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ALTER '.$field_name.' SET DEFAULT '.$default_value) ? true : false;
- $result &= $this->query('UPDATE '.($no_prefix ? '' : $this->prefix).$table_name.' SET '.$field_name.'='.$default_value) ? true : false;
- }
-
- if (!$allow_null)
- $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' ALTER '.$field_name.' SET NOT NULL') ? true : false;
-
- return $result;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = null, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
-
- $result = $this->add_field($table_name, 'tmp_'.$field_name, $field_type, $allow_null, $default_value, $after_field, $no_prefix);
- $result &= $this->query('UPDATE '.($no_prefix ? '' : $this->prefix).$table_name.' SET tmp_'.$field_name.' = '.$field_name) ? true : false;
- $result &= $this->drop_field($table_name, $field_name, $no_prefix);
- $result &= $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' RENAME COLUMN tmp_'.$field_name.' TO '.$field_name) ? true : false;
-
- return $result;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- return $this->query('ALTER TABLE '.($no_prefix ? '' : $this->prefix).$table_name.' DROP '.$field_name) ? true : false;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('CREATE '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ON '.($no_prefix ? '' : $this->prefix).$table_name.'('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('DELETE FROM '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/dblayer/sqlite.php b/upload/include/dblayer/sqlite.php
deleted file mode 100644
index 49ffeb8..0000000
--- a/upload/include/dblayer/sqlite.php
+++ /dev/null
@@ -1,528 +0,0 @@
- 'INTEGER',
- '/^(TINY|SMALL|MEDIUM|BIG)?INT( )?(\\([0-9]+\\))?( )?(UNSIGNED)?$/i' => 'INTEGER',
- '/^(TINY|MEDIUM|LONG)?TEXT$/i' => 'TEXT'
- );
-
-
- function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix, $p_connect)
- {
- // Prepend $db_name with the path to the forum root directory
- $db_name = PUN_ROOT.$db_name;
-
- $this->prefix = $db_prefix;
-
- if (!file_exists($db_name))
- {
- @touch($db_name);
- @chmod($db_name, 0666);
- if (!file_exists($db_name))
- error('Unable to create new database \''.$db_name.'\'. Permission denied', __FILE__, __LINE__);
- }
-
- if (!is_readable($db_name))
- error('Unable to open database \''.$db_name.'\' for reading. Permission denied', __FILE__, __LINE__);
-
- if (!is_writable($db_name))
- error('Unable to open database \''.$db_name.'\' for writing. Permission denied', __FILE__, __LINE__);
-
- if ($p_connect)
- $this->link_id = @sqlite_popen($db_name, 0666, $sqlite_error);
- else
- $this->link_id = @sqlite_open($db_name, 0666, $sqlite_error);
-
- if (!$this->link_id)
- error('Unable to open database \''.$db_name.'\'. SQLite reported: '.$sqlite_error, __FILE__, __LINE__);
- else
- return $this->link_id;
- }
-
-
- function start_transaction()
- {
- ++$this->in_transaction;
-
- return (@sqlite_query($this->link_id, 'BEGIN')) ? true : false;
- }
-
-
- function end_transaction()
- {
- --$this->in_transaction;
-
- if (@sqlite_query($this->link_id, 'COMMIT'))
- return true;
- else
- {
- @sqlite_query($this->link_id, 'ROLLBACK');
- return false;
- }
- }
-
-
- function query($sql, $unbuffered = false)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $q_start = get_microtime();
-
- if ($unbuffered)
- $this->query_result = @sqlite_unbuffered_query($this->link_id, $sql);
- else
- $this->query_result = @sqlite_query($this->link_id, $sql);
-
- if ($this->query_result)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, sprintf('%.5f', get_microtime() - $q_start));
-
- ++$this->num_queries;
-
- return $this->query_result;
- }
- else
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array($sql, 0);
-
- $this->error_no = @sqlite_last_error($this->link_id);
- $this->error_msg = @sqlite_error_string($this->error_no);
-
- if ($this->in_transaction)
- @sqlite_query($this->link_id, 'ROLLBACK');
-
- --$this->in_transaction;
-
- return false;
- }
- }
-
-
- function result($query_id = 0, $row = 0, $col = 0)
- {
- if ($query_id)
- {
- if ($row != 0)
- @sqlite_seek($query_id, $row);
-
- $cur_row = @sqlite_current($query_id);
- return $cur_row[$col];
- }
- else
- return false;
- }
-
-
- function fetch_assoc($query_id = 0)
- {
- if ($query_id)
- {
- $cur_row = @sqlite_fetch_array($query_id, SQLITE_ASSOC);
- if ($cur_row)
- {
- // Horrible hack to get rid of table names and table aliases from the array keys
- foreach ($cur_row as $key => $value)
- {
- $dot_spot = strpos($key, '.');
- if ($dot_spot !== false)
- {
- unset($cur_row[$key]);
- $key = substr($key, $dot_spot+1);
- $cur_row[$key] = $value;
- }
- }
- }
-
- return $cur_row;
- }
- else
- return false;
- }
-
-
- function fetch_row($query_id = 0)
- {
- return ($query_id) ? @sqlite_fetch_array($query_id, SQLITE_NUM) : false;
- }
-
-
- function num_rows($query_id = 0)
- {
- return ($query_id) ? @sqlite_num_rows($query_id) : false;
- }
-
-
- function affected_rows()
- {
- return ($this->query_result) ? @sqlite_changes($this->query_result) : false;
- }
-
-
- function insert_id()
- {
- return ($this->link_id) ? @sqlite_last_insert_rowid($this->link_id) : false;
- }
-
-
- function get_num_queries()
- {
- return $this->num_queries;
- }
-
-
- function get_saved_queries()
- {
- return $this->saved_queries;
- }
-
-
- function free_result($query_id = false)
- {
- return true;
- }
-
-
- function escape($str)
- {
- return is_array($str) ? '' : sqlite_escape_string($str);
- }
-
-
- function error()
- {
- $result['error_sql'] = @current(@end($this->saved_queries));
- $result['error_no'] = $this->error_no;
- $result['error_msg'] = $this->error_msg;
-
- return $result;
- }
-
-
- function close()
- {
- if ($this->link_id)
- {
- if ($this->in_transaction)
- {
- if (defined('PUN_SHOW_QUERIES'))
- $this->saved_queries[] = array('COMMIT', 0);
-
- @sqlite_query($this->link_id, 'COMMIT');
- }
-
- return @sqlite_close($this->link_id);
- }
- else
- return false;
- }
-
- function set_names($names)
- {
- return;
- }
-
-
- function get_version()
- {
- return array(
- 'name' => 'SQLite',
- 'version' => sqlite_libversion()
- );
- }
-
-
- function table_exists($table_name, $no_prefix = false)
- {
- $result = $this->query('SELECT 1 FROM sqlite_master WHERE name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND type=\'table\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function field_exists($table_name, $field_name, $no_prefix = false)
- {
- $result = $this->query('SELECT sql FROM sqlite_master WHERE name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND type=\'table\'');
- if (!$this->num_rows($result))
- return false;
-
- return preg_match('/[\r\n]'.preg_quote($field_name).' /', $this->result($result));
- }
-
-
- function index_exists($table_name, $index_name, $no_prefix = false)
- {
- $result = $this->query('SELECT 1 FROM sqlite_master WHERE tbl_name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' AND name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_'.$this->escape($index_name).'\' AND type=\'index\'');
- return $this->num_rows($result) > 0;
- }
-
-
- function create_table($table_name, $schema, $no_prefix = false)
- {
- if ($this->table_exists($table_name, $no_prefix))
- return true;
-
- $query = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$table_name." (\n";
-
- // Go through every schema element and add it to the query
- foreach ($schema['FIELDS'] as $field_name => $field_data)
- {
- $field_data['datatype'] = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_data['datatype']);
-
- $query .= $field_name.' '.$field_data['datatype'];
-
- if (!$field_data['allow_null'])
- $query .= ' NOT NULL';
-
- if (isset($field_data['default']))
- $query .= ' DEFAULT '.$field_data['default'];
-
- $query .= ",\n";
- }
-
- // If we have a primary key, add it
- if (isset($schema['PRIMARY KEY']))
- $query .= 'PRIMARY KEY ('.implode(',', $schema['PRIMARY KEY']).'),'."\n";
-
- // Add unique keys
- if (isset($schema['UNIQUE KEYS']))
- {
- foreach ($schema['UNIQUE KEYS'] as $key_name => $key_fields)
- $query .= 'UNIQUE ('.implode(',', $key_fields).'),'."\n";
- }
-
- // We remove the last two characters (a newline and a comma) and add on the ending
- $query = substr($query, 0, strlen($query) - 2)."\n".')';
-
- $result = $this->query($query) ? true : false;
-
- // Add indexes
- if (isset($schema['INDEXES']))
- {
- foreach ($schema['INDEXES'] as $index_name => $index_fields)
- $result &= $this->add_index($table_name, $index_name, $index_fields, false, $no_prefix);
- }
-
- return $result;
- }
-
-
- function drop_table($table_name, $no_prefix = false)
- {
- if (!$this->table_exists($table_name, $no_prefix))
- return true;
-
- return $this->query('DROP TABLE '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-
-
- function get_table_info($table_name, $no_prefix = false)
- {
- // Grab table info
- $result = $this->query('SELECT sql FROM sqlite_master WHERE tbl_name = \''.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'\' ORDER BY type DESC') or error('Unable to fetch table information', __FILE__, __LINE__, $this->error());
- $num_rows = $this->num_rows($result);
-
- if ($num_rows == 0)
- return;
-
- $table = array();
- $table['indices'] = array();
- while ($cur_index = $this->fetch_assoc($result))
- {
- if (empty($cur_index['sql']))
- continue;
-
- if (!isset($table['sql']))
- $table['sql'] = $cur_index['sql'];
- else
- $table['indices'][] = $cur_index['sql'];
- }
-
- // Work out the columns in the table currently
- $table_lines = explode("\n", $table['sql']);
- $table['columns'] = array();
- foreach ($table_lines as $table_line)
- {
- $table_line = pun_trim($table_line);
- if (substr($table_line, 0, 12) == 'CREATE TABLE')
- continue;
- else if (substr($table_line, 0, 11) == 'PRIMARY KEY')
- $table['primary_key'] = $table_line;
- else if (substr($table_line, 0, 6) == 'UNIQUE')
- $table['unique'] = $table_line;
- else if (substr($table_line, 0, strpos($table_line, ' ')) != '')
- $table['columns'][substr($table_line, 0, strpos($table_line, ' '))] = pun_trim(substr($table_line, strpos($table_line, ' ')));
- }
-
- return $table;
- }
-
-
- function add_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = 0, $no_prefix = false)
- {
- if ($this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $table = $this->get_table_info($table_name, $no_prefix);
-
- // Create temp table
- $now = time();
- $tmptable = str_replace('CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (', 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' (', $table['sql']);
- $result = $this->query($tmptable) ? true : false;
- $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name)) ? true : false;
-
- // Create new table sql
- $field_type = preg_replace(array_keys($this->datatype_transformations), array_values($this->datatype_transformations), $field_type);
- $query = $field_type;
- if (!$allow_null)
- $query .= ' NOT NULL';
- if ($default_value === null || $default_value === '')
- $default_value = '\'\'';
-
- $query .= ' DEFAULT '.$default_value;
-
- $old_columns = array_keys($table['columns']);
- array_insert($table['columns'], $after_field, $query.',', $field_name);
-
- $new_table = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (';
-
- foreach ($table['columns'] as $cur_column => $column_details)
- $new_table .= "\n".$cur_column.' '.$column_details;
-
- if (isset($table['unique']))
- $new_table .= "\n".$table['unique'].',';
-
- if (isset($table['primary_key']))
- $new_table .= "\n".$table['primary_key'];
-
- $new_table = trim($new_table, ',')."\n".');';
-
- // Drop old table
- $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name));
-
- // Create new table
- $result &= $this->query($new_table) ? true : false;
-
- // Recreate indexes
- if (!empty($table['indices']))
- {
- foreach ($table['indices'] as $cur_index)
- $result &= $this->query($cur_index) ? true : false;
- }
-
- // Copy content back
- $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' ('.implode(', ', $old_columns).') SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now) ? true : false;
-
- // Drop temp table
- $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now);
-
- return $result;
- }
-
-
- function alter_field($table_name, $field_name, $field_type, $allow_null, $default_value = null, $after_field = 0, $no_prefix = false)
- {
- // Unneeded for SQLite
- return true;
- }
-
-
- function drop_field($table_name, $field_name, $no_prefix = false)
- {
- if (!$this->field_exists($table_name, $field_name, $no_prefix))
- return true;
-
- $table = $this->get_table_info($table_name, $no_prefix);
-
- // Create temp table
- $now = time();
- $tmptable = str_replace('CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (', 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' (', $table['sql']);
- $result = $this->query($tmptable) ? true : false;
- $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now.' SELECT * FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name)) ? true : false;
-
- // Work out the columns we need to keep and the sql for the new table
- unset($table['columns'][$field_name]);
- $new_columns = array_keys($table['columns']);
-
- $new_table = 'CREATE TABLE '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' (';
-
- foreach ($table['columns'] as $cur_column => $column_details)
- $new_table .= "\n".$cur_column.' '.$column_details;
-
- if (isset($table['unique']))
- $new_table .= "\n".$table['unique'].',';
-
- if (isset($table['primary_key']))
- $new_table .= "\n".$table['primary_key'];
-
- $new_table = trim($new_table, ',')."\n".');';
-
- // Drop old table
- $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name));
-
- // Create new table
- $result &= $this->query($new_table) ? true : false;
-
- // Recreate indexes
- if (!empty($table['indices']))
- {
- foreach ($table['indices'] as $cur_index)
- if (!preg_match('%\('.preg_quote($field_name, '%').'\)%', $cur_index))
- $result &= $this->query($cur_index) ? true : false;
- }
-
- // Copy content back
- $result &= $this->query('INSERT INTO '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).' SELECT '.implode(', ', $new_columns).' FROM '.($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now) ? true : false;
-
- // Drop temp table
- $result &= $this->drop_table(($no_prefix ? '' : $this->prefix).$this->escape($table_name).'_t'.$now);
-
- return $result;
- }
-
-
- function add_index($table_name, $index_name, $index_fields, $unique = false, $no_prefix = false)
- {
- if ($this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('CREATE '.($unique ? 'UNIQUE ' : '').'INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name.' ON '.($no_prefix ? '' : $this->prefix).$table_name.'('.implode(',', $index_fields).')') ? true : false;
- }
-
-
- function drop_index($table_name, $index_name, $no_prefix = false)
- {
- if (!$this->index_exists($table_name, $index_name, $no_prefix))
- return true;
-
- return $this->query('DROP INDEX '.($no_prefix ? '' : $this->prefix).$table_name.'_'.$index_name) ? true : false;
- }
-
- function truncate_table($table_name, $no_prefix = false)
- {
- return $this->query('DELETE FROM '.($no_prefix ? '' : $this->prefix).$table_name) ? true : false;
- }
-}
diff --git a/upload/include/email.php b/upload/include/email.php
deleted file mode 100644
index 5df0ef0..0000000
--- a/upload/include/email.php
+++ /dev/null
@@ -1,186 +0,0 @@
- 80)
- return false;
-
- return preg_match('/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|("[^"]+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\d\-]+\.)+[a-zA-Z]{2,}))$/', $email);
-}
-
-
-//
-// Check if $email is banned
-//
-function is_banned_email($email)
-{
- global $db, $pun_bans;
-
- foreach ($pun_bans as $cur_ban)
- {
- if ($cur_ban['email'] != '' &&
- ($email == $cur_ban['email'] ||
- (strpos($cur_ban['email'], '@') === false && stristr($email, '@'.$cur_ban['email']))))
- return true;
- }
-
- return false;
-}
-
-
-//
-// Wrapper for PHP's mail()
-//
-function pun_mail($to, $subject, $message, $reply_to_email = '', $reply_to_name = '')
-{
- global $pun_config, $lang_common;
-
- // Default sender/return address
- $from_name = str_replace('"', '', $pun_config['o_board_title'].' '.$lang_common['Mailer']);
- $from_email = $pun_config['o_webmaster_email'];
-
- // Do a little spring cleaning
- $to = pun_trim(preg_replace('#[\n\r]+#s', '', $to));
- $subject = pun_trim(preg_replace('#[\n\r]+#s', '', $subject));
- $from_email = pun_trim(preg_replace('#[\n\r:]+#s', '', $from_email));
- $from_name = pun_trim(preg_replace('#[\n\r:]+#s', '', str_replace('"', '', $from_name)));
- $reply_to_email = pun_trim(preg_replace('#[\n\r:]+#s', '', $reply_to_email));
- $reply_to_name = pun_trim(preg_replace('#[\n\r:]+#s', '', str_replace('"', '', $reply_to_name)));
-
- // Set up some headers to take advantage of UTF-8
- $from = "=?UTF-8?B?".base64_encode($from_name)."?=".' <'.$from_email.'>';
- $subject = "=?UTF-8?B?".base64_encode($subject)."?=";
-
- $headers = 'From: '.$from."\r\n".'Date: '.gmdate('r')."\r\n".'MIME-Version: 1.0'."\r\n".'Content-transfer-encoding: 8bit'."\r\n".'Content-type: text/plain; charset=utf-8'."\r\n".'X-Mailer: FluxBB Mailer';
-
- // If we specified a reply-to email, we deal with it here
- if (!empty($reply_to_email))
- {
- $reply_to = "=?UTF-8?B?".base64_encode($reply_to_name)."?=".' <'.$reply_to_email.'>';
-
- $headers .= "\r\n".'Reply-To: '.$reply_to;
- }
-
- // Make sure all linebreaks are CRLF in message (and strip out any NULL bytes)
- $message = str_replace(array("\n", "\0"), array("\r\n", ''), pun_linebreaks($message));
-
- if ($pun_config['o_smtp_host'] != '')
- smtp_mail($to, $subject, $message, $headers);
- else
- {
- // Change the linebreaks used in the headers according to OS
- if (strtoupper(substr(PHP_OS, 0, 3)) == 'MAC')
- $headers = str_replace("\r\n", "\r", $headers);
- else if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN')
- $headers = str_replace("\r\n", "\n", $headers);
-
- mail($to, $subject, $message, $headers);
- }
-}
-
-
-//
-// This function was originally a part of the phpBB Group forum software phpBB2 (http://www.phpbb.com)
-// They deserve all the credit for writing it. I made small modifications for it to suit PunBB and it's coding standards
-//
-function server_parse($socket, $expected_response)
-{
- $server_response = '';
- while (substr($server_response, 3, 1) != ' ')
- {
- if (!($server_response = fgets($socket, 256)))
- error('Couldn\'t get mail server response codes. Please contact the forum administrator.', __FILE__, __LINE__);
- }
-
- if (!(substr($server_response, 0, 3) == $expected_response))
- error('Unable to send email. Please contact the forum administrator with the following error message reported by the SMTP server: "'.$server_response.'"', __FILE__, __LINE__);
-}
-
-
-//
-// This function was originally a part of the phpBB Group forum software phpBB2 (http://www.phpbb.com)
-// They deserve all the credit for writing it. I made small modifications for it to suit PunBB and it's coding standards.
-//
-function smtp_mail($to, $subject, $message, $headers = '')
-{
- global $pun_config;
-
- $recipients = explode(',', $to);
-
- // Sanitize the message
- $message = str_replace("\r\n.", "\r\n..", $message);
- $message = (substr($message, 0, 1) == '.' ? '.'.$message : $message);
-
- // Are we using port 25 or a custom port?
- if (strpos($pun_config['o_smtp_host'], ':') !== false)
- list($smtp_host, $smtp_port) = explode(':', $pun_config['o_smtp_host']);
- else
- {
- $smtp_host = $pun_config['o_smtp_host'];
- $smtp_port = 25;
- }
-
- if ($pun_config['o_smtp_ssl'] == '1')
- $smtp_host = 'ssl://'.$smtp_host;
-
- if (!($socket = fsockopen($smtp_host, $smtp_port, $errno, $errstr, 15)))
- error('Could not connect to smtp host "'.$pun_config['o_smtp_host'].'" ('.$errno.') ('.$errstr.')', __FILE__, __LINE__);
-
- server_parse($socket, '220');
-
- if ($pun_config['o_smtp_user'] != '' && $pun_config['o_smtp_pass'] != '')
- {
- fwrite($socket, 'EHLO '.$smtp_host."\r\n");
- server_parse($socket, '250');
-
- fwrite($socket, 'AUTH LOGIN'."\r\n");
- server_parse($socket, '334');
-
- fwrite($socket, base64_encode($pun_config['o_smtp_user'])."\r\n");
- server_parse($socket, '334');
-
- fwrite($socket, base64_encode($pun_config['o_smtp_pass'])."\r\n");
- server_parse($socket, '235');
- }
- else
- {
- fwrite($socket, 'HELO '.$smtp_host."\r\n");
- server_parse($socket, '250');
- }
-
- fwrite($socket, 'MAIL FROM: <'.$pun_config['o_webmaster_email'].'>'."\r\n");
- server_parse($socket, '250');
-
- foreach ($recipients as $email)
- {
- fwrite($socket, 'RCPT TO: <'.$email.'>'."\r\n");
- server_parse($socket, '250');
- }
-
- fwrite($socket, 'DATA'."\r\n");
- server_parse($socket, '354');
-
- fwrite($socket, 'Subject: '.$subject."\r\n".'To: <'.implode('>, <', $recipients).'>'."\r\n".$headers."\r\n\r\n".$message."\r\n");
-
- fwrite($socket, '.'."\r\n");
- server_parse($socket, '250');
-
- fwrite($socket, 'QUIT'."\r\n");
- fclose($socket);
-
- return true;
-}
diff --git a/upload/include/functions.php b/upload/include/functions.php
deleted file mode 100644
index d66298e..0000000
--- a/upload/include/functions.php
+++ /dev/null
@@ -1,1627 +0,0 @@
- 1, 'password_hash' => 'Guest');
-
- // If a cookie is set, we get the user_id and password hash from it
- if (isset($_COOKIE[$cookie_name]))
- list($cookie['user_id'], $cookie['password_hash'], $cookie['expiration_time']) = @unserialize($_COOKIE[$cookie_name]);
-
- if ($cookie['user_id'] > 1)
- {
- // Check if there's a user with the user ID and password hash from the cookie
- $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($cookie['user_id'])) or error('Unable to fetch user information', __FILE__, __LINE__, $db->error());
- $pun_user = $db->fetch_assoc($result);
-
- // If user authorisation failed
- if (!isset($pun_user['id']) || md5($cookie_seed.$pun_user['password']) !== $cookie['password_hash'])
- {
- $expire = $now + 31536000; // The cookie expires after a year
- pun_setcookie(1, md5(uniqid(rand(), true)), $expire);
- set_default_user();
-
- return;
- }
-
- // Send a new, updated cookie with a new expiration timestamp
- $expire = (intval($cookie['expiration_time']) > $now + $pun_config['o_timeout_visit']) ? $now + 1209600 : $now + $pun_config['o_timeout_visit'];
- pun_setcookie($pun_user['id'], $pun_user['password'], $expire);
-
- // Set a default language if the user selected language no longer exists
- if (!file_exists(PUN_ROOT.'lang/'.$pun_user['language']))
- $pun_user['language'] = $pun_config['o_default_lang'];
-
- // Set a default style if the user selected style no longer exists
- if (!file_exists(PUN_ROOT.'style/'.$pun_user['style'].'.css'))
- $pun_user['style'] = $pun_config['o_default_style'];
-
- if (!$pun_user['disp_topics'])
- $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
- if (!$pun_user['disp_posts'])
- $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
-
- // Define this if you want this visit to affect the online list and the users last visit data
- if (!defined('PUN_QUIET_VISIT'))
- {
- // Update the online list
- if (!$pun_user['logged'])
- {
- $pun_user['logged'] = $now;
-
- // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- case 'sqlite':
- $db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES('.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
- break;
-
- default:
- $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT '.$pun_user['id'].', \''.$db->escape($pun_user['username']).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE user_id='.$pun_user['id'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
- break;
- }
-
- // Reset tracked topics
- set_tracked_topics(null);
- }
- else
- {
- // Special case: We've timed out, but no other user has browsed the forums since we timed out
- if ($pun_user['logged'] < ($now-$pun_config['o_timeout_visit']))
- {
- $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
- $pun_user['last_visit'] = $pun_user['logged'];
- }
-
- $idle_sql = ($pun_user['idle'] == '1') ? ', idle=0' : '';
- $db->query('UPDATE '.$db->prefix.'online SET logged='.$now.$idle_sql.' WHERE user_id='.$pun_user['id']) or error('Unable to update online list', __FILE__, __LINE__, $db->error());
- }
- }
- else
- {
- if (!$pun_user['logged'])
- $pun_user['logged'] = $pun_user['last_visit'];
- }
-
- $pun_user['is_guest'] = false;
- $pun_user['is_admmod'] = $pun_user['g_id'] == PUN_ADMIN || $pun_user['g_moderator'] == '1';
- }
- else
- set_default_user();
-}
-
-
-//
-// Converts the CDATA end sequence ]]> into ]]>
-//
-function escape_cdata($str)
-{
- return str_replace(']]>', ']]>', $str);
-}
-
-
-//
-// Authenticates the provided username and password against the user database
-// $user can be either a user ID (integer) or a username (string)
-// $password can be either a plaintext password or a password hash including salt ($password_is_hash must be set accordingly)
-//
-function authenticate_user($user, $password, $password_is_hash = false)
-{
- global $db, $pun_user;
-
- // Check if there's a user matching $user and $password
- $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE '.(is_int($user) ? 'u.id='.intval($user) : 'u.username=\''.$db->escape($user).'\'')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
- $pun_user = $db->fetch_assoc($result);
-
- if (!isset($pun_user['id']) ||
- ($password_is_hash && $password != $pun_user['password']) ||
- (!$password_is_hash && pun_hash($password) != $pun_user['password']))
- set_default_user();
- else
- $pun_user['is_guest'] = false;
-}
-
-
-//
-// Try to determine the current URL
-//
-function get_current_url($max_length = 0)
-{
- $protocol = (!isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off') ? 'http://' : 'https://';
- $port = (isset($_SERVER['SERVER_PORT']) && (($_SERVER['SERVER_PORT'] != '80' && $protocol == 'http://') || ($_SERVER['SERVER_PORT'] != '443' && $protocol == 'https://')) && strpos($_SERVER['HTTP_HOST'], ':') === false) ? ':'.$_SERVER['SERVER_PORT'] : '';
-
- $url = urldecode($protocol.$_SERVER['HTTP_HOST'].$port.$_SERVER['REQUEST_URI']);
-
- if (strlen($url) <= $max_length || $max_length == 0)
- return $url;
-
- // We can't find a short enough url
- return null;
-}
-
-
-//
-// Fill $pun_user with default values (for guests)
-//
-function set_default_user()
-{
- global $db, $db_type, $pun_user, $pun_config;
-
- $remote_addr = get_remote_address();
-
- // Fetch guest user
- $result = $db->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.ident=\''.$remote_addr.'\' WHERE u.id=1') or error('Unable to fetch guest information', __FILE__, __LINE__, $db->error());
- if (!$db->num_rows($result))
- exit('Unable to fetch guest information. The table \''.$db->prefix.'users\' must contain an entry with id = 1 that represents anonymous users.');
-
- $pun_user = $db->fetch_assoc($result);
-
- // Update online list
- if (!$pun_user['logged'])
- {
- $pun_user['logged'] = time();
-
- // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- case 'sqlite':
- $db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
- break;
-
- default:
- $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT 1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($remote_addr).'\')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
- break;
- }
- }
- else
- $db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error());
-
- $pun_user['disp_topics'] = $pun_config['o_disp_topics_default'];
- $pun_user['disp_posts'] = $pun_config['o_disp_posts_default'];
- $pun_user['timezone'] = $pun_config['o_default_timezone'];
- $pun_user['dst'] = $pun_config['o_default_dst'];
- $pun_user['language'] = $pun_config['o_default_lang'];
- $pun_user['style'] = $pun_config['o_default_style'];
- $pun_user['is_guest'] = true;
- $pun_user['is_admmod'] = false;
-}
-
-
-//
-// Set a cookie, FluxBB style!
-// Wrapper for forum_setcookie
-//
-function pun_setcookie($user_id, $password_hash, $expire)
-{
- global $cookie_name, $cookie_seed;
-
- forum_setcookie($cookie_name, serialize(array($user_id, md5($cookie_seed.$password_hash), $expire)), $expire);
-}
-
-
-//
-// Set a cookie, FluxBB style!
-//
-function forum_setcookie($name, $value, $expire)
-{
- global $cookie_path, $cookie_domain, $cookie_secure;
-
- // Enable sending of a P3P header
- header('P3P: CP="CUR ADM"');
-
- if (version_compare(PHP_VERSION, '5.2.0', '>='))
- setcookie($name, $value, $expire, $cookie_path, $cookie_domain, $cookie_secure, true);
- else
- setcookie($name, $value, $expire, $cookie_path.'; HttpOnly', $cookie_domain, $cookie_secure);
-}
-
-
-//
-// Check whether the connecting user is banned (and delete any expired bans while we're at it)
-//
-function check_bans()
-{
- global $db, $pun_config, $lang_common, $pun_user, $pun_bans;
-
- // Admins aren't affected
- if ($pun_user['g_id'] == PUN_ADMIN || !$pun_bans)
- return;
-
- // Add a dot or a colon (depending on IPv4/IPv6) at the end of the IP address to prevent banned address
- // 192.168.0.5 from matching e.g. 192.168.0.50
- $user_ip = get_remote_address();
- $user_ip .= (strpos($user_ip, '.') !== false) ? '.' : ':';
-
- $bans_altered = false;
- $is_banned = false;
-
- foreach ($pun_bans as $cur_ban)
- {
- // Has this ban expired?
- if ($cur_ban['expire'] != '' && $cur_ban['expire'] <= time())
- {
- $db->query('DELETE FROM '.$db->prefix.'bans WHERE id='.$cur_ban['id']) or error('Unable to delete expired ban', __FILE__, __LINE__, $db->error());
- $bans_altered = true;
- continue;
- }
-
- if ($cur_ban['username'] != '' && utf8_strtolower($pun_user['username']) == utf8_strtolower($cur_ban['username']))
- $is_banned = true;
-
- if ($cur_ban['ip'] != '')
- {
- $cur_ban_ips = explode(' ', $cur_ban['ip']);
-
- $num_ips = count($cur_ban_ips);
- for ($i = 0; $i < $num_ips; ++$i)
- {
- // Add the proper ending to the ban
- if (strpos($user_ip, '.') !== false)
- $cur_ban_ips[$i] = $cur_ban_ips[$i].'.';
- else
- $cur_ban_ips[$i] = $cur_ban_ips[$i].':';
-
- if (substr($user_ip, 0, strlen($cur_ban_ips[$i])) == $cur_ban_ips[$i])
- {
- $is_banned = true;
- break;
- }
- }
- }
-
- if ($is_banned)
- {
- $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($pun_user['username']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
- message($lang_common['Ban message'].' '.(($cur_ban['expire'] != '') ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : '').(($cur_ban['message'] != '') ? $lang_common['Ban message 3'].'
'.pun_htmlspecialchars($cur_ban['message']).'
' : '
').$lang_common['Ban message 4'].' '.$pun_config['o_admin_email'].'.', true);
- }
- }
-
- // If we removed any expired bans during our run-through, we need to regenerate the bans cache
- if ($bans_altered)
- {
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_bans_cache();
- }
-}
-
-
-//
-// Check username
-//
-function check_username($username, $exclude_id = null)
-{
- global $db, $pun_config, $errors, $lang_prof_reg, $lang_register, $lang_common, $pun_bans;
-
- // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames)
- $username = preg_replace('#\s+#s', ' ', $username);
-
- // Validate username
- if (pun_strlen($username) < 2)
- $errors[] = $lang_prof_reg['Username too short'];
- else if (pun_strlen($username) > 25) // This usually doesn't happen since the form element only accepts 25 characters
- $errors[] = $lang_prof_reg['Username too long'];
- else if (!strcasecmp($username, 'Guest') || !strcasecmp($username, $lang_common['Guest']))
- $errors[] = $lang_prof_reg['Username guest'];
- else if (preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $username) || preg_match('/((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))/', $username))
- $errors[] = $lang_prof_reg['Username IP'];
- else if ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false)
- $errors[] = $lang_prof_reg['Username reserved chars'];
- else if (preg_match('/(?:\[\/?(?:b|u|i|h|colou?r|quote|code|img|url|email|list|\*)\]|\[(?:img|url|quote|list)=)/i', $username))
- $errors[] = $lang_prof_reg['Username BBCode'];
-
- // Check username for any censored words
- if ($pun_config['o_censoring'] == '1' && censor_words($username) != $username)
- $errors[] = $lang_register['Username censor'];
-
- // Check that the username (or a too similar username) is not already registered
- $query = ($exclude_id) ? ' AND id!='.$exclude_id : '';
-
- $result = $db->query('SELECT username FROM '.$db->prefix.'users WHERE (UPPER(username)=UPPER(\''.$db->escape($username).'\') OR UPPER(username)=UPPER(\''.$db->escape(preg_replace('/[^\w]/', '', $username)).'\')) AND id>1'.$query) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result))
- {
- $busy = $db->result($result);
- $errors[] = $lang_register['Username dupe 1'].' '.pun_htmlspecialchars($busy).'. '.$lang_register['Username dupe 2'];
- }
-
- // Check username for any banned usernames
- foreach ($pun_bans as $cur_ban)
- {
- if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username']))
- {
- $errors[] = $lang_prof_reg['Banned username'];
- break;
- }
- }
-}
-
-
-//
-// Update "Users online"
-//
-function update_users_online()
-{
- global $db, $pun_config;
-
- $now = time();
-
- // Fetch all online list entries that are older than "o_timeout_online"
- $result = $db->query('SELECT user_id, ident, logged, idle FROM '.$db->prefix.'online WHERE logged<'.($now-$pun_config['o_timeout_online'])) or error('Unable to fetch old entries from online list', __FILE__, __LINE__, $db->error());
- while ($cur_user = $db->fetch_assoc($result))
- {
- // If the entry is a guest, delete it
- if ($cur_user['user_id'] == '1')
- $db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($cur_user['ident']).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
- else
- {
- // If the entry is older than "o_timeout_visit", update last_visit for the user in question, then delete him/her from the online list
- if ($cur_user['logged'] < ($now-$pun_config['o_timeout_visit']))
- {
- $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$cur_user['logged'].' WHERE id='.$cur_user['user_id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error());
- $db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$cur_user['user_id']) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
- }
- else if ($cur_user['idle'] == '0')
- $db->query('UPDATE '.$db->prefix.'online SET idle=1 WHERE user_id='.$cur_user['user_id']) or error('Unable to insert into online list', __FILE__, __LINE__, $db->error());
- }
- }
-}
-
-
-//
-// Generate the "navigator" that appears at the top of every page
-//
-function generate_navlinks()
-{
- global $pun_config, $lang_common, $pun_user;
-
- // Index and Userlist should always be displayed
- $links[] = '
';
- }
- }
-
- // Are there any additional navlinks we should insert into the array before imploding it?
- if ($pun_config['o_additional_navlinks'] != '')
- {
- if (preg_match_all('#([0-9]+)\s*=\s*(.*?)\n#s', $pun_config['o_additional_navlinks']."\n", $extra_links))
- {
- // Insert any additional links into the $links array (at the correct index)
- $num_links = count($extra_links[1]);
- for ($i = 0; $i < $num_links; ++$i)
- array_splice($links, $extra_links[1][$i], 0, array('
';
-}
-
-
-//
-// Display the profile navigation menu
-//
-function generate_profile_menu($page = '')
-{
- global $lang_profile, $pun_config, $pun_user, $id;
-
-?>
-
-
-
-
-
-
-
>
-
>
-
>
-
>
-
>
-
>
-
>
-
-
-
-
-';
- break;
- }
- }
-
- return $avatar_markup;
-}
-
-
-//
-// Generate browser's title
-//
-function generate_page_title($page_title, $p = null)
-{
- global $pun_config, $lang_common;
-
- $page_title = array_reverse($page_title);
-
- if ($p != null)
- $page_title[0] .= ' ('.sprintf($lang_common['Page'], forum_number_format($p)).')';
-
- $crumbs = implode($lang_common['Title separator'], $page_title);
-
- return $crumbs;
-}
-
-
-//
-// Save array of tracked topics in cookie
-//
-function set_tracked_topics($tracked_topics)
-{
- global $cookie_name, $cookie_path, $cookie_domain, $cookie_secure, $pun_config;
-
- $cookie_data = '';
- if (!empty($tracked_topics))
- {
- // Sort the arrays (latest read first)
- arsort($tracked_topics['topics'], SORT_NUMERIC);
- arsort($tracked_topics['forums'], SORT_NUMERIC);
-
- // Homebrew serialization (to avoid having to run unserialize() on cookie data)
- foreach ($tracked_topics['topics'] as $id => $timestamp)
- $cookie_data .= 't'.$id.'='.$timestamp.';';
- foreach ($tracked_topics['forums'] as $id => $timestamp)
- $cookie_data .= 'f'.$id.'='.$timestamp.';';
-
- // Enforce a 4048 byte size limit (4096 minus some space for the cookie name)
- if (strlen($cookie_data) > 4048)
- {
- $cookie_data = substr($cookie_data, 0, 4048);
- $cookie_data = substr($cookie_data, 0, strrpos($cookie_data, ';')).';';
- }
- }
-
- forum_setcookie($cookie_name.'_track', $cookie_data, time() + $pun_config['o_timeout_visit']);
- $_COOKIE[$cookie_name.'_track'] = $cookie_data; // Set it directly in $_COOKIE as well
-}
-
-
-//
-// Extract array of tracked topics from cookie
-//
-function get_tracked_topics()
-{
- global $cookie_name;
-
- $cookie_data = isset($_COOKIE[$cookie_name.'_track']) ? $_COOKIE[$cookie_name.'_track'] : false;
- if (!$cookie_data)
- return array('topics' => array(), 'forums' => array());
-
- if (strlen($cookie_data) > 4048)
- return array('topics' => array(), 'forums' => array());
-
- // Unserialize data from cookie
- $tracked_topics = array('topics' => array(), 'forums' => array());
- $temp = explode(';', $cookie_data);
- foreach ($temp as $t)
- {
- $type = substr($t, 0, 1) == 'f' ? 'forums' : 'topics';
- $id = intval(substr($t, 1));
- $timestamp = intval(substr($t, strpos($t, '=') + 1));
- if ($id > 0 && $timestamp > 0)
- $tracked_topics[$type][$id] = $timestamp;
- }
-
- return $tracked_topics;
-}
-
-
-//
-// Update posts, topics, last_post, last_post_id and last_poster for a forum
-//
-function update_forum($forum_id)
-{
- global $db;
-
- $result = $db->query('SELECT COUNT(id), SUM(num_replies) FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id) or error('Unable to fetch forum topic count', __FILE__, __LINE__, $db->error());
- list($num_topics, $num_posts) = $db->fetch_row($result);
-
- $num_posts = $num_posts + $num_topics; // $num_posts is only the sum of all replies (we have to add the topic posts)
-
- $result = $db->query('SELECT last_post, last_post_id, last_poster FROM '.$db->prefix.'topics WHERE forum_id='.$forum_id.' AND moved_to IS NULL ORDER BY last_post DESC LIMIT 1') or error('Unable to fetch last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
- if ($db->num_rows($result)) // There are topics in the forum
- {
- list($last_post, $last_post_id, $last_poster) = $db->fetch_row($result);
-
- $db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post='.$last_post.', last_post_id='.$last_post_id.', last_poster=\''.$db->escape($last_poster).'\' WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
- }
- else // There are no topics
- $db->query('UPDATE '.$db->prefix.'forums SET num_topics='.$num_topics.', num_posts='.$num_posts.', last_post=NULL, last_post_id=NULL, last_poster=NULL WHERE id='.$forum_id) or error('Unable to update last_post/last_post_id/last_poster', __FILE__, __LINE__, $db->error());
-}
-
-
-//
-// Deletes any avatars owned by the specified user ID
-//
-function delete_avatar($user_id)
-{
- global $pun_config;
-
- $filetypes = array('jpg', 'gif', 'png');
-
- // Delete user avatar
- foreach ($filetypes as $cur_type)
- {
- if (file_exists(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$user_id.'.'.$cur_type))
- @unlink(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$user_id.'.'.$cur_type);
- }
-}
-
-
-//
-// Delete a topic and all of it's posts
-//
-function delete_topic($topic_id)
-{
- global $db;
-
- // Delete the topic and any redirect topics
- $db->query('DELETE FROM '.$db->prefix.'topics WHERE id='.$topic_id.' OR moved_to='.$topic_id) or error('Unable to delete topic', __FILE__, __LINE__, $db->error());
-
- // Create a list of the post IDs in this topic
- $post_ids = '';
- $result = $db->query('SELECT id FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch posts', __FILE__, __LINE__, $db->error());
- while ($row = $db->fetch_row($result))
- $post_ids .= ($post_ids != '') ? ','.$row[0] : $row[0];
-
- // Make sure we have a list of post IDs
- if ($post_ids != '')
- {
- strip_search_index($post_ids);
-
- // Delete posts in topic
- $db->query('DELETE FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to delete posts', __FILE__, __LINE__, $db->error());
- }
-
- // Delete any subscriptions for this topic
- $db->query('DELETE FROM '.$db->prefix.'subscriptions WHERE topic_id='.$topic_id) or error('Unable to delete subscriptions', __FILE__, __LINE__, $db->error());
-}
-
-
-//
-// Delete a single post
-//
-function delete_post($post_id, $topic_id)
-{
- global $db;
-
- $result = $db->query('SELECT id, poster, posted FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id.' ORDER BY id DESC LIMIT 2') or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
- list($last_id, ,) = $db->fetch_row($result);
- list($second_last_id, $second_poster, $second_posted) = $db->fetch_row($result);
-
- // Delete the post
- $db->query('DELETE FROM '.$db->prefix.'posts WHERE id='.$post_id) or error('Unable to delete post', __FILE__, __LINE__, $db->error());
-
- strip_search_index($post_id);
-
- // Count number of replies in the topic
- $result = $db->query('SELECT COUNT(id) FROM '.$db->prefix.'posts WHERE topic_id='.$topic_id) or error('Unable to fetch post count for topic', __FILE__, __LINE__, $db->error());
- $num_replies = $db->result($result, 0) - 1;
-
- // If the message we deleted is the most recent in the topic (at the end of the topic)
- if ($last_id == $post_id)
- {
- // If there is a $second_last_id there is more than 1 reply to the topic
- if (!empty($second_last_id))
- $db->query('UPDATE '.$db->prefix.'topics SET last_post='.$second_posted.', last_post_id='.$second_last_id.', last_poster=\''.$db->escape($second_poster).'\', num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
- else
- // We deleted the only reply, so now last_post/last_post_id/last_poster is posted/id/poster from the topic itself
- $db->query('UPDATE '.$db->prefix.'topics SET last_post=posted, last_post_id=id, last_poster=poster, num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
- }
- else
- // Otherwise we just decrement the reply counter
- $db->query('UPDATE '.$db->prefix.'topics SET num_replies='.$num_replies.' WHERE id='.$topic_id) or error('Unable to update topic', __FILE__, __LINE__, $db->error());
-}
-
-
-//
-// Delete every .php file in the forum's cache directory
-//
-function forum_clear_cache()
-{
- $d = dir(FORUM_CACHE_DIR);
- while (($entry = $d->read()) !== false)
- {
- if (substr($entry, strlen($entry)-4) == '.php')
- @unlink(FORUM_CACHE_DIR.$entry);
- }
- $d->close();
-}
-
-
-//
-// Replace censored words in $text
-//
-function censor_words($text)
-{
- global $db;
- static $search_for, $replace_with;
-
- // If not already built in a previous call, build an array of censor words and their replacement text
- if (!isset($search_for))
- {
- $result = $db->query('SELECT search_for, replace_with FROM '.$db->prefix.'censoring') or error('Unable to fetch censor word list', __FILE__, __LINE__, $db->error());
- $num_words = $db->num_rows($result);
-
- $search_for = array();
- for ($i = 0; $i < $num_words; ++$i)
- {
- list($search_for[$i], $replace_with[$i]) = $db->fetch_row($result);
- $search_for[$i] = '/\b('.str_replace('\*', '\w*?', preg_quote($search_for[$i], '/')).')\b/i';
- }
- }
-
- if (!empty($search_for))
- $text = substr(preg_replace($search_for, $replace_with, ' '.$text.' '), 1, -1);
-
- return $text;
-}
-
-
-//
-// Determines the correct title for $user
-// $user must contain the elements 'username', 'title', 'posts', 'g_id' and 'g_user_title'
-//
-function get_title($user)
-{
- global $db, $pun_config, $pun_bans, $lang_common;
- static $ban_list, $pun_ranks;
-
- // If not already built in a previous call, build an array of lowercase banned usernames
- if (empty($ban_list))
- {
- $ban_list = array();
-
- foreach ($pun_bans as $cur_ban)
- $ban_list[] = strtolower($cur_ban['username']);
- }
-
- // If not already loaded in a previous call, load the cached ranks
- if ($pun_config['o_ranks'] == '1' && empty($pun_ranks))
- {
- if (file_exists(FORUM_CACHE_DIR.'cache_ranks.php'))
- include FORUM_CACHE_DIR.'cache_ranks.php';
-
- if (!defined('PUN_RANKS_LOADED'))
- {
- if (!defined('FORUM_CACHE_FUNCTIONS_LOADED'))
- require PUN_ROOT.'include/cache.php';
-
- generate_ranks_cache();
- require FORUM_CACHE_DIR.'cache_ranks.php';
- }
- }
-
- // If the user has a custom title
- if ($user['title'] != '')
- $user_title = pun_htmlspecialchars($user['title']);
- // If the user is banned
- else if (in_array(strtolower($user['username']), $ban_list))
- $user_title = $lang_common['Banned'];
- // If the user group has a default user title
- else if ($user['g_user_title'] != '')
- $user_title = pun_htmlspecialchars($user['g_user_title']);
- // If the user is a guest
- else if ($user['g_id'] == PUN_GUEST)
- $user_title = $lang_common['Guest'];
- else
- {
- // Are there any ranks?
- if ($pun_config['o_ranks'] == '1' && !empty($pun_ranks))
- {
- foreach ($pun_ranks as $cur_rank)
- {
- if (intval($user['num_posts']) >= $cur_rank['min_posts'])
- $user_title = pun_htmlspecialchars($cur_rank['rank']);
- }
- }
-
- // If the user didn't "reach" any rank (or if ranks are disabled), we assign the default
- if (!isset($user_title))
- $user_title = $lang_common['Member'];
- }
-
- return $user_title;
-}
-
-
-//
-// Generate a string with numbered links (for multipage scripts)
-//
-function paginate($num_pages, $cur_page, $link)
-{
- global $lang_common;
-
- $pages = array();
- $link_to_all = false;
-
- // If $cur_page == -1, we link to all pages (used in viewforum.php)
- if ($cur_page == -1)
- {
- $cur_page = 1;
- $link_to_all = true;
- }
-
- if ($num_pages <= 1)
- $pages = array('1');
- else
- {
- // Add a previous page link
- if ($num_pages > 1 && $cur_page > 1)
- $pages[] = ''.$lang_common['Previous'].'';
-
- if ($cur_page > 3)
- {
- $pages[] = '1';
-
- if ($cur_page > 5)
- $pages[] = ''.$lang_common['Spacer'].'';
- }
-
- // Don't ask me how the following works. It just does, OK? :-)
- for ($current = ($cur_page == 5) ? $cur_page - 3 : $cur_page - 2, $stop = ($cur_page + 4 == $num_pages) ? $cur_page + 4 : $cur_page + 3; $current < $stop; ++$current)
- {
- if ($current < 1 || $current > $num_pages)
- continue;
- else if ($current != $cur_page || $link_to_all)
- $pages[] = ''.forum_number_format($current).'';
- else
- $pages[] = ''.forum_number_format($current).'';
- }
-
- if ($cur_page <= ($num_pages-3))
- {
- if ($cur_page != ($num_pages-3) && $cur_page != ($num_pages-4))
- $pages[] = ''.$lang_common['Spacer'].'';
-
- $pages[] = ''.forum_number_format($num_pages).'';
- }
-
- // Add a next page link
- if ($num_pages > 1 && !$link_to_all && $cur_page < $num_pages)
- $pages[] = ''.$lang_common['Next'].'';
- }
-
- return implode(' ', $pages);
-}
-
-
-//
-// Display a message
-//
-function message($message, $no_back_link = false)
-{
- global $db, $lang_common, $pun_config, $pun_start, $tpl_main;
-
- if (!defined('PUN_HEADER'))
- {
- global $pun_user;
-
- $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang_common['Info']);
- define('PUN_ACTIVE_PAGE', 'index');
- require PUN_ROOT.'header.php';
- }
-
-?>
-
-
';
- }
- }
- }
-
- // Add paragraph tag around post, but make sure there are no empty paragraphs
- $text = preg_replace('# \s*? ((\s* )*)#i', "
$1
", $text);
- $text = str_replace('
', '
', $text);
- $text = str_replace('
', '', '
'.$text.'
');
-
- return $text;
-}
-
-
-//
-// Parse signature text
-//
-function parse_signature($text)
-{
- global $pun_config, $lang_common, $pun_user;
-
- if ($pun_config['o_censoring'] == '1')
- $text = censor_words($text);
-
- // Convert applicable characters to HTML entities
- $text = pun_htmlspecialchars($text);
-
- if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
- $text = do_bbcode($text, true);
-
- if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] == '1')
- $text = do_smilies($text);
-
-
- // Deal with newlines, tabs and multiple spaces
- $pattern = array("\n", "\t", ' ', ' ');
- $replace = array(' ', ' ', ' ', ' ');
- $text = str_replace($pattern, $replace, $text);
-
- // Add paragraph tag around post, but make sure there are no empty paragraphs
- $text = preg_replace('# \s*? ((\s* )*)#i', "$1
", $text);
- $text = str_replace('
', '
', $text);
- $text = str_replace('
', '', '
'.$text.'
');
-
- return $text;
-}
diff --git a/upload/include/search_idx.php b/upload/include/search_idx.php
deleted file mode 100644
index 1214676..0000000
--- a/upload/include/search_idx.php
+++ /dev/null
@@ -1,311 +0,0 @@
-`"„\|,@_\?%~\+\[\]{}:=\/#\\\\;!\*\.…\s•]+/u', ' ', $text);
-
- // Replace multiple dashes with just one
- $text = preg_replace('/-{2,}/', '-', $text);
-
- // Fill an array with all the words
- $words = array_unique(explode(' ', $text));
-
- // Remove any words that should not be indexed
- foreach ($words as $key => $value)
- {
- // If the word shouldn't be indexed, remove it
- if (!validate_search_word($value, $idx))
- unset($words[$key]);
- }
-
- return $words;
-}
-
-
-//
-// Checks if a word is a valid searchable word
-//
-function validate_search_word($word, $idx)
-{
- global $pun_user, $pun_config;
- static $stopwords;
-
- // If the word is a keyword we don't want to index it, but we do want to be allowed to search it
- if (is_keyword($word))
- return !$idx;
-
- $language = isset($pun_user['language']) ? $pun_user['language'] : $pun_config['o_default_lang'];
- if (!isset($stopwords))
- {
- if (file_exists(PUN_ROOT.'lang/'.$language.'/stopwords.txt'))
- {
- $stopwords = file(PUN_ROOT.'lang/'.$language.'/stopwords.txt');
- $stopwords = array_map('pun_trim', $stopwords);
- $stopwords = array_filter($stopwords);
- }
- else
- $stopwords = array();
- }
-
- // If it is a stopword it isn't valid
- if (in_array($word, $stopwords))
- return false;
-
- // If the word if CJK we don't want to index it, but we do want to be allowed to search it
- if (is_cjk($word))
- return !$idx;
-
- // Check the word is within the min/max length
- $num_chars = pun_strlen($word);
- return $num_chars >= PUN_SEARCH_MIN_WORD && $num_chars <= PUN_SEARCH_MAX_WORD;
-}
-
-
-//
-// Check a given word is a search keyword.
-//
-function is_keyword($word)
-{
- return $word == 'and' || $word == 'or' || $word == 'not';
-}
-
-
-//
-// Check if a given word is CJK or Hangul.
-//
-function is_cjk($word)
-{
- return preg_match('/^'.PUN_CJK_HANGUL_REGEX.'+$/u', $word) ? true : false;
-}
-
-
-//
-// Strip [img] [url] and [email] out of the message so we don't index their contents
-//
-function strip_bbcode($text)
-{
- static $patterns;
-
- if (!isset($patterns))
- {
- $patterns = array(
- '%\[img=([^\]]*+)\][^[]*+\[/img\]%' => '$1', // Keep the alt description
- '%\[(url|email)=[^\]]*+\]([^[]*+(?:(?!\[/\1\])\[[^[]*+)*)\[/\1\]%' => '$2', // Keep the text
- '%\[(img|url|email)\]([^[]*+(?:(?!\[/\1\])\[[^[]*+)*)\[/\1\]%' => '', // Remove the whole thing
- );
- }
-
- return preg_replace(array_keys($patterns), array_values($patterns), $text);
-}
-
-
-//
-// Updates the search index with the contents of $post_id (and $subject)
-//
-function update_search_index($mode, $post_id, $message, $subject = null)
-{
- global $db_type, $db;
-
- $message = utf8_strtolower($message);
- $subject = utf8_strtolower($subject);
-
- // Remove any bbcode that we shouldn't index
- $message = strip_bbcode($message);
-
- // Split old and new post/subject to obtain array of 'words'
- $words_message = split_words($message, true);
- $words_subject = ($subject) ? split_words($subject, true) : array();
-
- if ($mode == 'edit')
- {
- $result = $db->query('SELECT w.id, w.word, m.subject_match FROM '.$db->prefix.'search_words AS w INNER JOIN '.$db->prefix.'search_matches AS m ON w.id=m.word_id WHERE m.post_id='.$post_id, true) or error('Unable to fetch search index words', __FILE__, __LINE__, $db->error());
-
- // Declare here to stop array_keys() and array_diff() from complaining if not set
- $cur_words['post'] = array();
- $cur_words['subject'] = array();
-
- while ($row = $db->fetch_row($result))
- {
- $match_in = ($row[2]) ? 'subject' : 'post';
- $cur_words[$match_in][$row[1]] = $row[0];
- }
-
- $db->free_result($result);
-
- $words['add']['post'] = array_diff($words_message, array_keys($cur_words['post']));
- $words['add']['subject'] = array_diff($words_subject, array_keys($cur_words['subject']));
- $words['del']['post'] = array_diff(array_keys($cur_words['post']), $words_message);
- $words['del']['subject'] = array_diff(array_keys($cur_words['subject']), $words_subject);
- }
- else
- {
- $words['add']['post'] = $words_message;
- $words['add']['subject'] = $words_subject;
- $words['del']['post'] = array();
- $words['del']['subject'] = array();
- }
-
- unset($words_message);
- unset($words_subject);
-
- // Get unique words from the above arrays
- $unique_words = array_unique(array_merge($words['add']['post'], $words['add']['subject']));
-
- if (!empty($unique_words))
- {
- $result = $db->query('SELECT id, word FROM '.$db->prefix.'search_words WHERE word IN(\''.implode('\',\'', array_map(array($db, 'escape'), $unique_words)).'\')', true) or error('Unable to fetch search index words', __FILE__, __LINE__, $db->error());
-
- $word_ids = array();
- while ($row = $db->fetch_row($result))
- $word_ids[$row[1]] = $row[0];
-
- $db->free_result($result);
-
- $new_words = array_diff($unique_words, array_keys($word_ids));
- unset($unique_words);
-
- if (!empty($new_words))
- {
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- $db->query('INSERT INTO '.$db->prefix.'search_words (word) VALUES(\''.implode('\'),(\'', array_map(array($db, 'escape'), $new_words)).'\')');
- break;
-
- default:
- foreach ($new_words as $word)
- $db->query('INSERT INTO '.$db->prefix.'search_words (word) VALUES(\''.$db->escape($word).'\')');
- break;
- }
- }
-
- unset($new_words);
- }
-
- // Delete matches (only if editing a post)
- foreach ($words['del'] as $match_in => $wordlist)
- {
- $subject_match = ($match_in == 'subject') ? 1 : 0;
-
- if (!empty($wordlist))
- {
- $sql = '';
- foreach ($wordlist as $word)
- $sql .= (($sql != '') ? ',' : '').$cur_words[$match_in][$word];
-
- $db->query('DELETE FROM '.$db->prefix.'search_matches WHERE word_id IN('.$sql.') AND post_id='.$post_id.' AND subject_match='.$subject_match) or error('Unable to delete search index word matches', __FILE__, __LINE__, $db->error());
- }
- }
-
- // Add new matches
- foreach ($words['add'] as $match_in => $wordlist)
- {
- $subject_match = ($match_in == 'subject') ? 1 : 0;
-
- if (!empty($wordlist))
- $db->query('INSERT INTO '.$db->prefix.'search_matches (post_id, word_id, subject_match) SELECT '.$post_id.', id, '.$subject_match.' FROM '.$db->prefix.'search_words WHERE word IN(\''.implode('\',\'', array_map(array($db, 'escape'), $wordlist)).'\')') or error('Unable to insert search index word matches', __FILE__, __LINE__, $db->error());
- }
-
- unset($words);
-}
-
-
-//
-// Strip search index of indexed words in $post_ids
-//
-function strip_search_index($post_ids)
-{
- global $db_type, $db;
-
- switch ($db_type)
- {
- case 'mysql':
- case 'mysqli':
- case 'mysql_innodb':
- case 'mysqli_innodb':
- {
- $result = $db->query('SELECT word_id FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.') GROUP BY word_id') or error('Unable to fetch search index word match', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result))
- {
- $word_ids = '';
- while ($row = $db->fetch_row($result))
- $word_ids .= ($word_ids != '') ? ','.$row[0] : $row[0];
-
- $result = $db->query('SELECT word_id FROM '.$db->prefix.'search_matches WHERE word_id IN('.$word_ids.') GROUP BY word_id HAVING COUNT(word_id)=1') or error('Unable to fetch search index word match', __FILE__, __LINE__, $db->error());
-
- if ($db->num_rows($result))
- {
- $word_ids = '';
- while ($row = $db->fetch_row($result))
- $word_ids .= ($word_ids != '') ? ','.$row[0] : $row[0];
-
- $db->query('DELETE FROM '.$db->prefix.'search_words WHERE id IN('.$word_ids.')') or error('Unable to delete search index word', __FILE__, __LINE__, $db->error());
- }
- }
-
- break;
- }
-
- default:
- $db->query('DELETE FROM '.$db->prefix.'search_words WHERE id IN(SELECT word_id FROM '.$db->prefix.'search_matches WHERE word_id IN(SELECT word_id FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.') GROUP BY word_id) GROUP BY word_id HAVING COUNT(word_id)=1)') or error('Unable to delete from search index', __FILE__, __LINE__, $db->error());
- break;
- }
-
- $db->query('DELETE FROM '.$db->prefix.'search_matches WHERE post_id IN('.$post_ids.')') or error('Unable to delete search index word match', __FILE__, __LINE__, $db->error());
-}
diff --git a/upload/include/template/admin.tpl b/upload/include/template/admin.tpl
deleted file mode 100644
index 1f6e007..0000000
--- a/upload/include/template/admin.tpl
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-query('SELECT user_id, ident FROM '.$db->prefix.'online WHERE idle=0 ORDER BY ident', true) or error('Unable to fetch online list', __FILE__, __LINE__, $db->error());
-
- while ($pun_user_online = $db->fetch_assoc($result))
- {
- if ($pun_user_online['user_id'] > 1)
- {
- if ($pun_user['g_view_users'] == '1')
- $users[] = "\n\t\t\t\t".'
-here instead.');
-}
-
-// Define PUN because email.php requires it
-define('PUN', 1);
-
-// Make sure we are running at least MIN_PHP_VERSION
-if (!function_exists('version_compare') || version_compare(PHP_VERSION, MIN_PHP_VERSION, '<'))
- exit('You are running PHP version '.PHP_VERSION.'. FluxBB '.FORUM_VERSION.' requires at least PHP '.MIN_PHP_VERSION.' to run properly. You must upgrade your PHP installation before you can continue.');
-
-// Load the functions script
-require PUN_ROOT.'include/functions.php';
-
-// Load UTF-8 functions
-require PUN_ROOT.'include/utf8/utf8.php';
-
-// Strip out "bad" UTF-8 characters
-forum_remove_bad_characters();
-
-// Reverse the effect of register_globals
-forum_unregister_globals();
-
-// Disable error reporting for uninitialized variables
-error_reporting(E_ALL);
-
-// Force POSIX locale (to prevent functions such as strtolower() from messing up UTF-8 strings)
-setlocale(LC_CTYPE, 'C');
-
-// Turn off magic_quotes_runtime
-if (get_magic_quotes_runtime())
- set_magic_quotes_runtime(0);
-
-// Strip slashes from GET/POST/COOKIE (if magic_quotes_gpc is enabled)
-if (get_magic_quotes_gpc())
-{
- function stripslashes_array($array)
- {
- return is_array($array) ? array_map('stripslashes_array', $array) : stripslashes($array);
- }
-
- $_GET = stripslashes_array($_GET);
- $_POST = stripslashes_array($_POST);
- $_COOKIE = stripslashes_array($_COOKIE);
- $_REQUEST = stripslashes_array($_REQUEST);
-}
-
-// Turn off PHP time limit
-@set_time_limit(0);
-
-//
-// Generate output to be used for config.php
-//
-function generate_config_file()
-{
- global $db_type, $db_host, $db_name, $db_username, $db_password, $db_prefix, $cookie_name, $cookie_seed;
-
- return ' 2)
- $dual_mysql = true;
- }
- if (function_exists('sqlite_open'))
- $db_extensions[] = array('sqlite', 'SQLite');
- if (function_exists('pg_connect'))
- $db_extensions[] = array('pgsql', 'PostgreSQL');
-
- if (empty($db_extensions))
- exit('This PHP environment does not have support for any of the databases that FluxBB supports. PHP needs to have support for either MySQL, PostgreSQL or SQLite in order for FluxBB to be installed.');
-
- // Make an educated guess regarding base_url
- $base_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; // protocol
- $base_url .= preg_replace('/:(80|443)$/', '', $_SERVER['HTTP_HOST']); // host[:port]
- $base_url .= str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])); // path
-
- if (substr($base_url, -1) == '/')
- $base_url = substr($base_url, 0, -1);
-
- $title = 'My FluxBB forum';
- $description = '
Unfortunately no one can be told what FluxBB is - you have to see it for yourself.
Welcome to FluxBB installation. You are about to install FluxBB. In order to install FluxBB, you must complete the form set out below. If you encounter any difficulties with the installation, please refer to the documentation.
-
-
-
-
-
-
-
Install FluxBB 1.4
-
-
-
-
-
-
Database setup
-
Please enter the requested information in order to setup your database for FluxBB. You must know all the information asked for before proceeding with the installation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Administration setup
-
Please enter the requested information in order to setup an administrator for your FluxBB installation.
-
-
-
-
-
-
-
-
-
-
-
-
Board setup
-
Please enter the requested information in order to setup your FluxBB board.
FluxBB has been installed. To finalize the installation please follow the instructions below.
-
-
-
-
-
-
-
-
Final instructions
-
-
-
-
-
-
To finalize the installation, you need to click on the button below to download a file called config.php. You then need to upload this file to the root directory of your FluxBB installation.
-
Once you have uploaded config.php, FluxBB will be fully installed! At that point, you may go to the forum index.
-
-
-
- 'No user by that username registered. If you want to add a ban not tied to a specific username just leave the username blank.',
-'No user ID message' => 'No user by that ID registered.',
-'User is admin message' => 'The user %s is an administrator and can\'t be banned. If you want to ban an administrator, you must first demote him/her to moderator or user.',
-'Must enter message' => 'You must enter either a username, an IP address or an email address (at least).',
-'Cannot ban guest message' => 'The guest user cannot be banned.',
-'Invalid IP message' => 'You entered an invalid IP/IP-range.',
-'Invalid e-mail message' => 'The email address (e.g. user@domain.com) or partial email address domain (e.g. domain.com) you entered is invalid.',
-'Invalid date message' => 'You entered an invalid expire date.',
-'Invalid date reasons' => 'The format should be YYYY-MM-DD and the date must be at least one day in the future.',
-'Ban added redirect' => 'Ban added. Redirecting …' ,
-'Ban edited redirect' => 'Ban edited. Redirecting …',
-'Ban removed redirect' => 'Ban removed. Redirecting …',
-
-'New ban head' => 'New ban',
-'Add ban subhead' => 'Add ban',
-'Username label' => 'Username',
-'Username help' => 'The username to ban (case-insensitive).',
-'Username advanced help' => 'The username to ban (case-insensitive). The next page will let you enter a custom IP and email. If you just want to ban a specific IP/IP-range or email just leave it blank.',
-
-'Ban search head' => 'Ban search',
-'Ban search subhead' => 'Enter search criteria',
-'Ban search info' => 'Search for bans in the database. You can enter one or more terms to search for. Wildcards in the form of asterisks (*) are accepted.',
-'Date help' => '(yyyy-mm-dd)',
-'Message label' => 'Message',
-'Expire after label' => 'Expire after',
-'Expire before label' => 'Expire before',
-'Order by label' => 'Order by',
-'Order by username' => 'Username',
-'Order by ip' => 'IP',
-'Order by e-mail' => 'Email',
-'Order by expire' => 'Expire date',
-'Ascending' => 'Ascending',
-'Descending' => 'Descending',
-'Submit search' => 'Submit search',
-
-'E-mail label' => 'Email',
-'E-mail help' => 'The email or email domain you wish to ban (e.g. someone@somewhere.com or somewhere.com). See "Allow banned email addresses" in Permissions for more info.',
-'IP label' => 'IP address/IP-ranges',
-'IP help' => 'The IP address or IP-ranges you wish to ban (e.g. 150.11.110.1 or 150.11.110). Separate addresses with spaces. If an IP is entered already it is the last known IP of this user in the database.',
-'IP help link' => 'Click %s to see IP statistics for this user.',
-'Reason label' => 'Reason',
-'Banned by label' => 'Banned by',
-'Ban advanced head' => 'Ban advanced settings',
-'Ban advanced subhead' => 'Supplement ban with IP and email',
-'Ban message label' => 'Ban message',
-'Ban message help' => 'A message that will be displayed to the banned user when he/she visits the board.',
-'Message expiry subhead' => 'Ban message and expiry',
-'Ban IP range info' => 'You should be very careful when banning an IP-range because of the possibility of multiple users matching the same partial IP.',
-'Expire date label' => 'Expire date',
-'Expire date help' => 'The date when this ban should be automatically removed (format: yyyy-mm-dd). Leave blank to remove manually.',
-
-'Results head' => 'Search Results',
-'Results username head' => 'Username',
-'Results e-mail head' => 'Email',
-'Results IP address head' => 'IP/IP-ranges',
-'Results expire head' => 'Expires',
-'Results message head' => 'Message',
-'Results banned by head' => 'Banned by',
-'Results actions head' => 'Actions',
-'No match' => 'No match',
-'Unknown' => 'Unknown',
-
-);
diff --git a/upload/lang/English/admin_categories.php b/upload/lang/English/admin_categories.php
deleted file mode 100644
index 311a5af..0000000
--- a/upload/lang/English/admin_categories.php
+++ /dev/null
@@ -1,29 +0,0 @@
- 'You must enter a name for the category',
-'Category added redirect' => 'Category added. Redirecting …',
-'Category deleted redirect' => 'Category deleted. Redirecting …',
-'Delete category head' => 'Delete category (together with all forums and posts it contains)',
-'Confirm delete subhead' => 'Confirm delete category',
-'Confirm delete info' => 'Are you sure that you want to delete the category %s?',
-'Delete category warn' => 'WARNING! Deleting a category will delete all forums and posts (if any) in this category!',
-'Must enter integer message' => 'Position must be a positive integer value.',
-'Categories updated redirect' => 'Categories updated. Redirecting …',
-'Add categories head' => 'Add categories',
-'Add categories subhead' => 'Add categories',
-'Add category label' => 'Add a new category',
-'Add new submit' => 'Add new',
-'Add category help' => 'The name of the new category you want to add. You can edit the name of the category later (see below). Go to %s to add forums to your new category.',
-'Delete categories head' => 'Delete categories',
-'Delete categories subhead' => 'Delete categories',
-'Delete category label' => 'Delete a category',
-'Delete category help' => 'Select the name of the category you want to delete. You will be asked to confirm your choice of category for deletion before it is deleted.',
-'Edit categories head' => 'Edit categories',
-'Edit categories subhead' => 'Edit categories',
-'Category position label' => 'Position',
-'Category name label' => 'Name',
-
-);
diff --git a/upload/lang/English/admin_censoring.php b/upload/lang/English/admin_censoring.php
deleted file mode 100644
index f112ba1..0000000
--- a/upload/lang/English/admin_censoring.php
+++ /dev/null
@@ -1,20 +0,0 @@
- 'You must enter both a word to censor and text to replace it with.',
-'Must search both message' => 'You must enter both text to search for and text to replace with.',
-'Word updated redirect' => 'Censor word updated. Redirecting …',
-'Word added redirect' => 'Censor word added. Redirecting …',
-'Word removed redirect' => 'Censor word removed. Redirecting …',
-'Censoring head' => 'Censoring',
-'Add word subhead' => 'Add word',
-'Add word info' => 'Enter a word that you want to censor and the replacement text for this word. Wildcards are accepted (i.e. *some* would match somewhere and lonesome). Censor words also affect usernames. New users will not be able to register with usernames containing any censored words. The search is case insensitive. Censor words must be enabled in %s for this to have any effect.',
-'Censored word label' => 'Censored word',
-'Replacement label' => 'Replacement word(s)',
-'Action label' => 'Action',
-'Edit remove subhead' => 'Edit or remove words',
-'No words in list' => 'No censor words in list.',
-
-);
diff --git a/upload/lang/English/admin_common.php b/upload/lang/English/admin_common.php
deleted file mode 100644
index a87616c..0000000
--- a/upload/lang/English/admin_common.php
+++ /dev/null
@@ -1,44 +0,0 @@
- 'Admin menu',
-'Plugins menu' => 'Plugins menu',
-'Moderator menu' => 'Moderator menu',
-'Index' => 'Index',
-'Categories' => 'Categories',
-'Forums' => 'Forums',
-'Users' => 'Users',
-'User groups' => 'User groups',
-'Options' => 'Options',
-'Permissions' => 'Permissions',
-'Censoring' => 'Censoring',
-'Ranks' => 'Ranks',
-'Bans' => 'Bans',
-'Prune' => 'Prune',
-'Maintenance' => 'Maintenance',
-'Reports' => 'Reports',
-
-'Admin' => 'Admin',
-'Go back' => 'Go back',
-'Delete' => 'Delete',
-'Update' => 'Update',
-'Add' => 'Add',
-'Edit' => 'Edit',
-'Remove' => 'Remove',
-'Yes' => 'Yes',
-'No' => 'No',
-'Save changes' => 'Save changes',
-'Save' => 'Save',
-'here' => 'here',
-'Action' => 'Action',
-'None' => 'None',
-'Maintenance mode' => 'maintenance mode', // Used for link text in more than one file
-
-// Admin loader
-'No plugin message' => 'There is no plugin called %s in the plugin directory.',
-'Plugin failed message' => 'Loading of the plugin - %s - failed.',
-
-);
diff --git a/upload/lang/English/admin_forums.php b/upload/lang/English/admin_forums.php
deleted file mode 100644
index f13876d..0000000
--- a/upload/lang/English/admin_forums.php
+++ /dev/null
@@ -1,51 +0,0 @@
- 'Forum added. Redirecting …',
-'Forum deleted redirect' => 'Forum deleted. Redirecting …',
-'Forums updated redirect' => 'Forums updated. Redirecting …',
-'Forum updated redirect' => 'Forum updated. Redirecting …',
-'Perms reverted redirect' => 'Permissions reverted to defaults. Redirecting …',
-'Must enter name message' => 'You must enter a forum name.',
-'Must be integer message' => 'Position must be a positive integer value.',
-
-// Entry page
-'Add forum head' => 'Add forum',
-'Create new subhead' => 'Create a new forum',
-'Add forum label' => 'Add forum to category',
-'Add forum help' => 'Select the category to which you wish to add a new forum.',
-'Add forum' => 'Add forum',
-'No categories exist' => 'No categories exist',
-'Edit forums head' => 'Edit forums',
-'Category subhead' => 'Category:',
-'Forum label' => 'Forum',
-'Edit link' => 'Edit',
-'Delete link' => 'Delete',
-'Position label' => 'Position',
-'Update positions' => 'Update positions',
-'Confirm delete head' => 'Confirm delete forum',
-'Confirm delete subhead' => 'Important! Read before deleting',
-'Confirm delete info' => 'Are you sure that you want to delete the forum %s?',
-'Confirm delete warn' => 'WARNING! Deleting a forum will delete all posts (if any) in that forum!',
-
-// Detailed edit page
-'Edit forum head' => 'Edit forum',
-'Edit details subhead' => 'Edit forum details',
-'Forum name label' => 'Forum name',
-'Forum description label' => 'Description (HTML)',
-'Category label' => 'Category',
-'Sort by label' => 'Sort topics by',
-'Last post' => 'Last post',
-'Topic start' => 'Topic start',
-'Redirect label' => 'Redirect URL',
-'Redirect help' => 'Only available in empty forums',
-'Group permissions subhead' => 'Edit group permissions for this forum',
-'Group permissions info' => 'In this form, you can set the forum specific permissions for the different user groups. If you haven\'t made any changes to this forum\'s group permissions, what you see below is the default based on settings in %s. Administrators always have full permissions and are thus excluded. Permission settings that differ from the default permissions for the user group are marked red. The "Read forum" permission checkbox will be disabled if the group in question lacks the "Read board" permission. For redirect forums, only the "Read forum" permission is editable.',
-'Read forum label' => 'Read forum',
-'Post replies label' => 'Post replies',
-'Post topics label' => 'Post topics',
-'Revert to default' => 'Revert to default',
-
-);
diff --git a/upload/lang/English/admin_groups.php b/upload/lang/English/admin_groups.php
deleted file mode 100644
index dd6ad56..0000000
--- a/upload/lang/English/admin_groups.php
+++ /dev/null
@@ -1,82 +0,0 @@
- 'You must enter a group title.',
-'Title already exists message' => 'There is already a group with the title %s.',
-'Default group redirect' => 'Default group set. Redirecting …',
-'Cannot remove default message' => 'The default group cannot be removed. In order to delete this group, you must first setup a different group as the default.',
-'Group removed redirect' => 'Group removed. Redirecting …',
-'Group added redirect' => 'Group added. Redirecting …',
-'Group edited redirect' => 'Group edited. Redirecting …',
-
-'Add groups head' => 'Add/setup groups',
-'Add group subhead' => 'Add new group',
-'New group label' => 'Base new group on',
-'New group help' => 'Select a user group from which the new group will inherit its permission settings. The next page will let you fine-tune its settings.',
-'Default group subhead' => 'Set default group',
-'Default group label' => 'Default group',
-'Default group help' => 'This is the default user group, e.g. the group users are placed in when they register. For security reasons, users can\'t be placed in either the moderator or administrator user groups by default.',
-'Existing groups head' => 'Existing groups',
-'Edit groups subhead' => 'Edit/delete groups',
-'Edit groups info' => 'The pre-defined groups Guests, Administrators, Moderators and Members cannot be removed. However, they can be edited. Please note that in some groups, some options are unavailable (e.g. the edit posts permission for guests). Administrators always have full permissions.',
-'Edit link' => 'Edit',
-'Delete link' => 'Delete',
-'Group delete head' => 'Group delete',
-'Confirm delete subhead' => 'Confirm delete group',
-'Confirm delete info' => 'Are you sure that you want to delete the group %s?',
-'Confirm delete warn' => 'WARNING! After you deleted a group you can not restore it.',
-'Delete group head' => 'Delete group',
-'Move users subhead' => 'Move users currently in group',
-'Move users info' => 'The group %s currently has %s members. Please select a group to which these members will be assigned upon deletion.',
-'Move users label' => 'Move users to',
-'Delete group' => 'Delete group',
-
-'Group settings head' => 'Group settings',
-'Group settings subhead' => 'Setup group options and permissions',
-'Group settings info' => 'Below options and permissions are the default permissions for the user group. These options apply if no forum specific permissions are in effect.',
-'Group title label' => 'Group title',
-'User title label' => 'User title',
-'User title help' => 'This title will override any rank users in this group have attained. Leave blank to use default title or rank.',
-'Mod privileges label' => 'Allow users moderator privileges',
-'Mod privileges help' => 'In order for a user in this group to have moderator abilities, he/she must be assigned to moderate one or more forums. This is done via the user administration page of the user\'s profile.',
-'Edit profile label' => 'Allow moderators to edit user profiles',
-'Edit profile help' => 'If moderator privileges are enabled, allow users in this group to edit user profiles.',
-'Rename users label' => 'Allow moderators to rename users',
-'Rename users help' => 'If moderator privileges are enabled, allow users in this group to rename users.',
-'Change passwords label' => 'Allow moderators to change passwords',
-'Change passwords help' => 'If moderator privileges are enabled, allow users in this group to change user passwords.',
-'Ban users label' => 'Allow moderators to ban users',
-'Ban users help' => 'If moderator privileges are enabled, allow users in this group to ban users.',
-'Read board label' => 'Read board',
-'Read board help' => 'Allow users in this group to view the board. This setting applies to every aspect of the board and can therefore not be overridden by forum specific settings. If this is set to "No", users in this group will only be able to login/logout and register.',
-'View user info label' => 'View user information',
-'View user info help' => 'Allow users to view the user list and user profiles.',
-'Post replies label' => 'Post replies',
-'Post replies help' => 'Allow users in this group to post replies in topics.',
-'Post topics label' => 'Post topics',
-'Post topics help' => 'Allow users in this group to post new topics.',
-'Edit posts label' => 'Edit posts',
-'Edit posts help' => 'Allow users in this group to edit their own posts.',
-'Delete posts label' => 'Delete posts',
-'Delete posts help' => 'Allow users in this group to delete their own posts.',
-'Delete topics label' => 'Delete topics',
-'Delete topics help' => 'Allow users in this group to delete their own topics (including any replies).',
-'Set own title label' => 'Set own user title',
-'Set own title help' => 'Allow users in this group to set their own user title.',
-'User search label' => 'Use search',
-'User search help' => 'Allow users in this group to use the search feature.',
-'User list search label' => 'Search user list',
-'User list search help' => 'Allow users in this group to freetext search for users in the user list.',
-'Send e-mails label' => 'Send e-mails',
-'Send e-mails help' => 'Allow users in this group to send e-mails to other users.',
-'Post flood label' => 'Post flood interval',
-'Post flood help' => 'Number of seconds that users in this group have to wait between posts. Set to 0 to disable.',
-'Search flood label' => 'Search flood interval',
-'Search flood help' => 'Number of seconds that users in this group have to wait between searches. Set to 0 to disable.',
-'E-mail flood label' => 'Email flood interval',
-'E-mail flood help' => 'Number of seconds that users in this group have to wait between emails. Set to 0 to disable.',
-'Moderator info' => 'Please note that in order for a user in this group to have moderator abilities, he/she must be assigned to moderate one or more forums. This is done via the user administration page of the user\'s profile.',
-
-);
diff --git a/upload/lang/English/admin_index.php b/upload/lang/English/admin_index.php
deleted file mode 100644
index 9f9cdc7..0000000
--- a/upload/lang/English/admin_index.php
+++ /dev/null
@@ -1,51 +0,0 @@
- 'Unable to check for upgrade since \'allow_url_fopen\' is disabled on this system.',
-'Upgrade check failed message' => 'Check for upgrade failed for unknown reasons.',
-'Running latest version message' => 'You are running the latest version of FluxBB.',
-'New version available message' => 'A new version of FluxBB has been released. You can download the latest version at %s.',
-'PHPinfo disabled message' => 'The PHP function phpinfo() has been disabled on this server.',
-'Not available' => 'Not available',
-'Forum admin head' => 'Forum administration',
-'NA' => 'N/A',
-'Welcome to admin' => 'Welcome to the FluxBB administration control panel. From here you can control vital aspects of the board. Depending on whether you are an administrator or a moderator you can:',
-'Welcome 1' => 'Organize categories and forums.',
-'Welcome 2' => 'Set forum-wide options and preferences.',
-'Welcome 3' => 'Control permissions for users and guests.',
-'Welcome 4' => 'View IP statistics for users.',
-'Welcome 5' => 'Ban users.',
-'Welcome 6' => 'Censor words.',
-'Welcome 7' => 'Set up user ranks.',
-'Welcome 8' => 'Prune old posts.',
-'Welcome 9' => 'Handle post reports.',
-'Statistics head' => 'Statistics',
-'FluxBB version label' => 'FluxBB version',
-'Check for upgrade' => 'Check for upgrade',
-'FluxBB version data' => 'v%s - %s',
-'Server load label' => 'Server load',
-'Server load data' => '%s - %s user(s) online',
-'Environment label' => 'Environment',
-'Environment data OS' => 'Operating system: %s',
-'Show info' => 'Show info',
-'Environment data version' => 'PHP: %s - %s',
-'Environment data acc' => 'Accelerator: %s',
-'Turck MMCache' => 'Turk MMCache',
-'Turck MMCache link' => 'turck-mmcache.sourceforge.net',
-'ionCube PHP Accelerator' => 'ionCube PHP Accelerator',
-'ionCube PHP Accelerator link' => 'www.php-accelerator.co.uk/',
-'Alternative PHP Cache (APC)' => 'Alternative PHP Cache (APC)',
-'Alternative PHP Cache (APC) link' => 'www.php.net/apc/',
-'Zend Optimizer' => 'Zend Optimizer',
-'Zend Optimizer link' => 'www.zend.com/products/guard/zend-optimizer',
-'eAccelerator' => 'eAccelerator',
-'eAccelerator link' => 'www.eaccelerator.net/',
-'XCache' => 'XCache',
-'XCache link' => 'xcache.lighttpd.net/',
-'Database label' => 'Database',
-'Database data rows' => 'Rows: %s',
-'Database data size' => 'Size: %s',
-
-);
diff --git a/upload/lang/English/admin_maintenance.php b/upload/lang/English/admin_maintenance.php
deleted file mode 100644
index a0e62b3..0000000
--- a/upload/lang/English/admin_maintenance.php
+++ /dev/null
@@ -1,23 +0,0 @@
- 'Forum maintenance',
-'Rebuild index subhead' => 'Rebuild search index',
-'Rebuild index info' => 'If you\'ve added, edited or removed posts manually in the database or if you\'re having problems searching, you should rebuild the search index. For best performance, you should put the forum in %s during rebuilding. Rebuilding the search index can take a long time and will increase server load during the rebuild process!',
-'Posts per cycle label' => 'Posts per cycle',
-'Posts per cycle help' => 'The number of posts to process per pageview. E.g. if you were to enter 300, three hundred posts would be processed and then the page would refresh. This is to prevent the script from timing out during the rebuild process.',
-'Starting post label' => 'Starting post ID',
-'Starting post help' => 'The post ID to start rebuilding at. The default value is the first available ID in the database. Normally you wouldn\'t want to change this.',
-'Empty index label' => 'Empty index',
-'Empty index help' => 'Select this if you want the search index to be emptied before rebuilding (see below).',
-'Rebuild completed info' => 'Once the process has completed, you will be redirected back to this page. It is highly recommended that you have JavaScript enabled in your browser during rebuilding (for automatic redirect when a cycle has completed). If you are forced to abort the rebuild process, make a note of the last processed post ID and enter that ID+1 in "Starting post ID" when/if you want to continue ("Empty index" must not be selected).',
-'Rebuild index' => 'Rebuild index',
-'Rebuilding search index' => 'Rebuilding search index',
-'Rebuilding index info' => 'Rebuilding index. This might be a good time to put on some coffee :-)',
-'Processing post' => 'Processing post %s …',
-'Click here' => 'Click here',
-'Javascript redirect failed' => 'JavaScript redirect unsuccessful. %s to continue …',
-
-);
diff --git a/upload/lang/English/admin_options.php b/upload/lang/English/admin_options.php
deleted file mode 100644
index e701917..0000000
--- a/upload/lang/English/admin_options.php
+++ /dev/null
@@ -1,217 +0,0 @@
- 'Bad HTTP_REFERER. If you have moved these forums from one location to another or switched domains, you need to update the Base URL manually in the database (look for o_base_url in the config table) and then clear the cache by deleting all .php files in the /cache directory.',
-'Must enter title message' => 'You must enter a board title.',
-'Invalid e-mail message' => 'The admin email address you entered is invalid.',
-'Invalid webmaster e-mail message' => 'The webmaster email address you entered is invalid.',
-'Enter announcement here' => 'Enter your announcement here.',
-'Enter rules here' => 'Enter your rules here.',
-'Default maintenance message' => 'The forums are temporarily down for maintenance. Please try again in a few minutes.',
-'Timeout error message' => 'The value of "Timeout online" must be smaller than the value of "Timeout visit".',
-'Options updated redirect' => 'Options updated. Redirecting …',
-'Options head' => 'Options',
-
-// Essentials section
-'Essentials subhead' => 'Essentials',
-'Board title label' => 'Board title',
-'Board title help' => 'The title of this bulletin board (shown at the top of every page). This field may not contain HTML.',
-'Board desc label' => 'Board description',
-'Board desc help' => 'A short description of this bulletin board (shown at the top of every page). This field may contain HTML.',
-'Base URL label' => 'Base URL',
-'Base URL help' => 'The complete URL of the board without trailing slash (i.e. http://www.mydomain.com/forums). This must be correct in order for all admin and moderator features to work. If you get "Bad referer" errors, it\'s probably incorrect.',
-'Timezone label' => 'Default time zone',
-'Timezone help' => 'The default time zone for guests and users attempting to register for the board.',
-'DST label' => 'Adjust for DST',
-'DST help' => 'Check if daylight savings is in effect (advances times by 1 hour).',
-'Language label' => 'Default language',
-'Language help' => 'The default language for guests and users who haven\'t changed from the default in their profile. If you remove a language pack, this must be updated.',
-'Default style label' => 'Default style',
-'Default style help' => 'The default style for guests and users who haven\'t changed from the default in their profile.',
-
-// Essentials section timezone options
-'UTC-12:00' => '(UTC-12:00) International Date Line West',
-'UTC-11:00' => '(UTC-11:00) Niue, Samoa',
-'UTC-10:00' => '(UTC-10:00) Hawaii-Aleutian, Cook Island',
-'UTC-09:30' => '(UTC-09:30) Marquesas Islands',
-'UTC-09:00' => '(UTC-09:00) Alaska, Gambier Island',
-'UTC-08:30' => '(UTC-08:30) Pitcairn Islands',
-'UTC-08:00' => '(UTC-08:00) Pacific',
-'UTC-07:00' => '(UTC-07:00) Mountain',
-'UTC-06:00' => '(UTC-06:00) Central',
-'UTC-05:00' => '(UTC-05:00) Eastern',
-'UTC-04:00' => '(UTC-04:00) Atlantic',
-'UTC-03:30' => '(UTC-03:30) Newfoundland',
-'UTC-03:00' => '(UTC-03:00) Amazon, Central Greenland',
-'UTC-02:00' => '(UTC-02:00) Mid-Atlantic',
-'UTC-01:00' => '(UTC-01:00) Azores, Cape Verde, Eastern Greenland',
-'UTC' => '(UTC) Western European, Greenwich',
-'UTC+01:00' => '(UTC+01:00) Central European, West African',
-'UTC+02:00' => '(UTC+02:00) Eastern European, Central African',
-'UTC+03:00' => '(UTC+03:00) Moscow, Eastern African',
-'UTC+03:30' => '(UTC+03:30) Iran',
-'UTC+04:00' => '(UTC+04:00) Gulf, Samara',
-'UTC+04:30' => '(UTC+04:30) Afghanistan',
-'UTC+05:00' => '(UTC+05:00) Pakistan, Yekaterinburg',
-'UTC+05:30' => '(UTC+05:30) India, Sri Lanka',
-'UTC+05:45' => '(UTC+05:45) Nepal',
-'UTC+06:00' => '(UTC+06:00) Bangladesh, Bhutan, Novosibirsk',
-'UTC+06:30' => '(UTC+06:30) Cocos Islands, Myanmar',
-'UTC+07:00' => '(UTC+07:00) Indochina, Krasnoyarsk',
-'UTC+08:00' => '(UTC+08:00) Greater China, Australian Western, Irkutsk',
-'UTC+08:45' => '(UTC+08:45) Southeastern Western Australia',
-'UTC+09:00' => '(UTC+09:00) Japan, Korea, Chita',
-'UTC+09:30' => '(UTC+09:30) Australian Central',
-'UTC+10:00' => '(UTC+10:00) Australian Eastern, Vladivostok',
-'UTC+10:30' => '(UTC+10:30) Lord Howe',
-'UTC+11:00' => '(UTC+11:00) Solomon Island, Magadan',
-'UTC+11:30' => '(UTC+11:30) Norfolk Island',
-'UTC+12:00' => '(UTC+12:00) New Zealand, Fiji, Kamchatka',
-'UTC+12:45' => '(UTC+12:45) Chatham Islands',
-'UTC+13:00' => '(UTC+13:00) Tonga, Phoenix Islands',
-'UTC+14:00' => '(UTC+14:00) Line Islands',
-
-// Timeout Section
-'Timeouts subhead' => 'Time and timeouts',
-'Time format label' => 'Time format',
-'PHP manual' => 'PHP manual',
-'Time format help' => '[Current format: %s]. See %s for formatting options.',
-'Date format label' => 'Date format',
-'Date format help' => '[Current format: %s]. See %s for formatting options.',
-'Visit timeout label' => 'Visit timeout',
-'Visit timeout help' => 'Number of seconds a user must be idle before his/hers last visit data is updated (primarily affects new message indicators).',
-'Online timeout label' => 'Online timeout',
-'Online timeout help' => 'Number of seconds a user must be idle before being removed from the online users list.',
-'Redirect time label' => 'Redirect time',
-'Redirect time help' => 'Number of seconds to wait when redirecting. If set to 0, no redirect page will be displayed (not recommended).',
-
-// Display Section
-'Display subhead' => 'Display',
-'Version number label' => 'Version number',
-'Version number help' => 'Show FluxBB version number in footer.',
-'Info in posts label' => 'User info in posts',
-'Info in posts help' => 'Show information about the poster under the username in topic view. The information affected is location, register date, post count and the contact links (email and URL).',
-'Post count label' => 'User post count',
-'Post count help' => 'Show the number of posts a user has made (affects topic view, profile and user list).',
-'Smilies label' => 'Smilies in posts',
-'Smilies help' => 'Convert smilies to small graphic icons.',
-'Smilies sigs label' => 'Smilies in signatures',
-'Smilies sigs help' => 'Convert smilies to small graphic icons in user signatures.',
-'Clickable links label' => 'Make clickable links',
-'Clickable links help' => 'When enabled, FluxBB will automatically detect any URLs in posts and make them clickable hyperlinks.',
-'Topic review label' => 'Topic review',
-'Topic review help' => 'Maximum number of posts to display when posting (newest first). Set to 0 to disable.',
-'Topics per page label' => 'Topics per page',
-'Topics per page help' => 'The default number of topics to display per page in a forum. Users can personalize this setting.',
-'Posts per page label' => 'Posts per page',
-'Posts per page help' => 'The default number of posts to display per page in a topic. Users can personalize this setting.',
-'Indent label' => 'Indent size',
-'Indent help' => 'If set to 8, a regular tab will be used when displaying text within the [code][/code] tag. Otherwise this many spaces will be used to indent the text.',
-'Quote depth label' => 'Maximum [quote] depth',
-'Quote depth help' => 'The maximum times a [quote] tag can go inside other [quote] tags, any tags deeper than this will be discarded.',
-
-// Features section
-'Features subhead' => 'Features',
-'Quick post label' => 'Quick post',
-'Quick post help' => 'When enabled, FluxBB will add a quick post form at the bottom of topics. This way users can post directly from the topic view.',
-'Users online label' => 'Users online',
-'Users online help' => 'Display info on the index page about guests and registered users currently browsing the board.',
-'Censor words label' => 'Censor words',
-'Censor words help' => 'Enable this to censor specific words in the board. See %s for more info.',
-'Signatures label' => 'Signatures',
-'Signatures help' => 'Allow users to attach a signature to their posts.',
-'User ranks label' => 'User ranks',
-'User ranks help' => 'Enable this to use user ranks. See %s for more info.',
-'User has posted label' => 'User has posted earlier',
-'User has posted help' => 'This feature displays a dot in front of topics in viewforum.php in case the currently logged in user has posted in that topic earlier. Disable if you are experiencing high server load.',
-'Topic views label' => 'Topic views',
-'Topic views help' => 'Keep track of the number of views a topic has. Disable if you are experiencing high server load in a busy forum.',
-'Quick jump label' => 'Quick jump',
-'Quick jump help' => 'Enable the quick jump (jump to forum) drop list.',
-'GZip label' => 'GZip output',
-'GZip help' => 'If enabled, FluxBB will gzip the output sent to browsers. This will reduce bandwidth usage, but use a little more CPU. This feature requires that PHP is configured with zlib (--with-zlib). Note: If you already have one of the Apache modules mod_gzip or mod_deflate set up to compress PHP scripts, you should disable this feature.',
-'Search all label' => 'Search all forums',
-'Search all help' => 'When disabled, searches will only be allowed in one forum at a time. Disable if server load is high due to excessive searching.',
-'Menu items label' => 'Additional menu items',
-'Menu items help' => 'By entering HTML hyperlinks into this textbox, any number of items can be added to the navigation menu at the top of all pages. The format for adding new links is X = <a href="URL">LINK</a> where X is the position at which the link should be inserted (e.g. 0 to insert at the beginning and 2 to insert after "User list"). Separate entries with a linebreak.',
-'Default feed label' => 'Default feed type',
-'Default feed help' => 'Select the type of syndication feed to display. Note: Choosing none will not disable feeds, only hide them by default.',
-'None' => 'None',
-'RSS' => 'RSS',
-'Atom' => 'Atom',
-
-// Reports section
-'Reports subhead' => 'Reports',
-'Reporting method label' => 'Reporting method',
-'Internal' => 'Internal',
-'By e-mail' => 'Email',
-'Both' => 'Both',
-'Reporting method help' => 'Select the method for handling topic/post reports. You can choose whether topic/post reports should be handled by the internal report system, emailed to the addresses on the mailing list (see below) or both.',
-'Mailing list label' => 'Mailing list',
-'Mailing list help' => 'A comma separated list of subscribers. The people on this list are the recipients of reports.',
-
-// Avatars section
-'Avatars subhead' => 'Avatars',
-'Use avatars label' => 'Use avatars',
-'Use avatars help' => 'When enabled, users will be able to upload an avatar which will be displayed under their title/rank.',
-'Upload directory label' => 'Upload directory',
-'Upload directory help' => 'The upload directory for avatars (relative to the FluxBB root directory). PHP must have write permissions to this directory.',
-'Max width label' => 'Max width',
-'Max width help' => 'The maximum allowed width of avatars in pixels (60 is recommended).',
-'Max height label' => 'Max height',
-'Max height help' => 'The maximum allowed height of avatars in pixels (60 is recommended).',
-'Max size label' => 'Max size',
-'Max size help' => 'The maximum allowed size of avatars in bytes (10240 is recommended).',
-
-// E-mail section
-'E-mail subhead' => 'Email',
-'Admin e-mail label' => 'Admin email',
-'Admin e-mail help' => 'The email address of the board administrator.',
-'Webmaster e-mail label' => 'Webmaster email',
-'Webmaster e-mail help' => 'This is the address that all emails sent by the board will be addressed from.',
-'Subscriptions label' => 'Subscriptions',
-'Subscriptions help' => 'Enable users to subscribe to topics (receive email when someone replies).',
-'SMTP address label' => 'SMTP server address',
-'SMTP address help' => 'The address of an external SMTP server to send emails with. You can specify a custom port number if the SMTP server doesn\'t run on the default port 25 (example: mail.myhost.com:3580). Leave blank to use the local mail program.',
-'SMTP username label' => 'SMTP username',
-'SMTP username help' => 'Username for SMTP server. Only enter a username if it is required by the SMTP server (most servers do not require authentication).',
-'SMTP password label' => 'SMTP password',
-'SMTP password help' => 'Password for SMTP server. Only enter a password if it is required by the SMTP server (most servers do not require authentication).',
-'SMTP SSL label' => 'Encrypt SMTP using SSL',
-'SMTP SSL help' => 'Encrypts the connection to the SMTP server using SSL. Should only be used if your SMTP server requires it and your version of PHP supports SSL.',
-
-// Registration Section
-'Registration subhead' => 'Registration',
-'Allow new label' => 'Allow new registrations',
-'Allow new help' => 'Controls whether this board accepts new registrations. Disable only under special circumstances.',
-'Verify label' => 'Verify registrations',
-'Verify help' => 'When enabled, users are emailed a random password when they register. They can then log in and change the password in their profile if they see fit. This feature also requires users to verify new email addresses if they choose to change from the one they registered with. This is an effective way of avoiding registration abuse and making sure that all users have "correct" email addresses in their profiles.',
-'Report new label' => 'Report new registrations',
-'Report new help' => 'If enabled, FluxBB will notify users on the mailing list (see above) when a new user registers in the forums.',
-'Use rules label' => 'User forum rules',
-'Use rules help' => 'When enabled, users must agree to a set of rules when registering (enter text below). The rules will always be available through a link in the navigation table at the top of every page.',
-'Rules label' => 'Enter your rules here',
-'Rules help' => 'Here you can enter any rules or other information that the user must review and accept when registering. If you enabled rules above you have to enter something here, otherwise it will be disabled. This text will not be parsed like regular posts and thus may contain HTML.',
-'E-mail default label' => 'Default email setting',
-'E-mail default help' => 'Choose the default privacy setting for new user registrations.',
-'Display e-mail label' => 'Display email address to other users.',
-'Hide allow form label' => 'Hide email address but allow form e-mail.',
-'Hide both label' => 'Hide email address and disallow form email.',
-
-// Announcement Section
-'Announcement subhead' => 'Announcements',
-'Display announcement label' => 'Display announcement',
-'Display announcement help' => 'Enable this to display the below message in the board.',
-'Announcement message label' => 'Announcement message',
-'Announcement message help' => 'This text will not be parsed like regular posts and thus may contain HTML.',
-
-// Maintenance Section
-'Maintenance subhead' => 'Maintenance',
-'Maintenance mode label' => 'Maintenance mode',
-'Maintenance mode help' => 'When enabled, the board will only be available to administrators. This should be used if the board needs to be taken down temporarily for maintenance. WARNING! Do not log out when the board is in maintenance mode. You will not be able to login again.',
-'Maintenance message label' => 'Maintenance message',
-'Maintenance message help' => 'The message that will be displayed to users when the board is in maintenance mode. If left blank, a default message will be used. This text will not be parsed like regular posts and thus may contain HTML.',
-
-);
diff --git a/upload/lang/English/admin_permissions.php b/upload/lang/English/admin_permissions.php
deleted file mode 100644
index 3c3600c..0000000
--- a/upload/lang/English/admin_permissions.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'Permissions updated. Redirecting …',
-'Permissions head' => 'Permissions',
-'Posting subhead' => 'Posting',
-'BBCode label' => 'BBCode',
-'BBCode help' => 'Allow BBCode in posts (recommended).',
-'Image tag label' => 'Image tag',
-'Image tag help' => 'Allow the BBCode [img][/img] tag in posts.',
-'All caps message label' => 'All caps message',
-'All caps message help' => 'Allow a message to contain only capital letters.',
-'All caps subject label' => 'All caps subject',
-'All caps subject help' => 'Allow a subject to contain only capital letters.',
-'Require e-mail label' => 'Require guest email',
-'Require e-mail help' => 'Require guests to supply an email address when posting.',
-'Signatures subhead' => 'Signatures',
-'BBCode sigs label' => 'BBCodes in signatures',
-'BBCode sigs help' => 'Allow BBCodes in user signatures.',
-'Image tag sigs label' => 'Image tag in signatures',
-'Image tag sigs help' => 'Allow the BBCode [img][/img] tag in user signatures (not recommended).',
-'All caps sigs label' => 'All caps signature',
-'All caps sigs help' => 'Allow a signature to contain only capital letters.',
-'Max sig length label' => 'Maximum signature length',
-'Max sig length help' => 'The maximum number of characters a user signature may contain.',
-'Max sig lines label' => 'Maximum signature lines',
-'Max sig lines help' => 'The maximum number of lines a user signature may contain.',
-'Registration subhead' => 'Registration',
-'Banned e-mail label' => 'Allow banned email addresses',
-'Banned e-mail help' => 'Allow users to register with or change to a banned email address/domain. If left at its default setting (yes), this action will be allowed, but an alert email will be sent to the mailing list (an effective way of detecting multiple registrations).',
-'Duplicate e-mail label' => 'Allow duplicate email addresses',
-'Duplicate e-mail help' => 'Controls whether users should be allowed to register with an email address that another user already has. If allowed, an alert email will be sent to the mailing list if a duplicate is detected.',
-
-);
diff --git a/upload/lang/English/admin_plugin_example.php b/upload/lang/English/admin_plugin_example.php
deleted file mode 100644
index b06158d..0000000
--- a/upload/lang/English/admin_plugin_example.php
+++ /dev/null
@@ -1,17 +0,0 @@
- 'You didn\'t enter anything!',
-'Example plugin title' => 'Example plugin',
-'You said' => 'You said "%s". Great stuff.',
-'Explanation 1' => 'This plugin doesn\'t do anything useful. Hence the name "Example".',
-'Explanation 2' => 'This would be a good spot to talk a little about your plugin. Describe what it does and how it should be used. Be brief, but informative.',
-'Example form title' => 'An example form',
-'Legend text' => 'Enter a piece of text and hit "Show text"!',
-'Text to show' => 'Text to show',
-'Show text button' => 'Show text',
-'Input content' => 'The text you want to display.',
-
-);
diff --git a/upload/lang/English/admin_prune.php b/upload/lang/English/admin_prune.php
deleted file mode 100644
index b7f9030..0000000
--- a/upload/lang/English/admin_prune.php
+++ /dev/null
@@ -1,23 +0,0 @@
- 'Days to prune must be a positive integer value.',
-'No old topics message' => 'There are no topics that are %s days old. Please decrease the value of "Days old" and try again.',
-'Posts pruned redirect' => 'Posts pruned. Redirecting …',
-'Prune head' => 'Prune',
-'Prune subhead' => 'Prune old posts',
-'Days old label' => 'Days old',
-'Days old help' => 'The number of days "old" a topic must be to be pruned. E.g. if you were to enter 30, every topic that didn\'t contain a post dated less than 30 days old would be deleted.',
-'Prune sticky label' => 'Prune sticky topics',
-'Prune sticky help' => 'When enabled sticky topics will also be pruned.',
-'Prune from label' => 'Prune from forum',
-'All forums' => 'All forums',
-'Prune from help' => 'The forum from which you want to prune posts.',
-'Prune info' => 'Use this feature with caution. Pruned posts can never be recovered. For best performance, you should put the forum in %s during pruning.',
-'Confirm prune subhead' => 'Confirm prune posts',
-'Confirm prune info' => 'Are you sure that you want to prune all topics older than %s days from %s (%s topics).',
-'Confirm prune warn' => 'WARNING! Pruning posts deletes them permanently.',
-
-);
diff --git a/upload/lang/English/admin_ranks.php b/upload/lang/English/admin_ranks.php
deleted file mode 100644
index 7dca408..0000000
--- a/upload/lang/English/admin_ranks.php
+++ /dev/null
@@ -1,21 +0,0 @@
- 'Minimum posts must be a positive integer value.',
-'Dupe min posts message' => 'There is already a rank with a minimun posts value of %s.',
-'Must enter title message' => 'You must enter a rank title.',
-'Rank added redirect' => 'Rank added. Redirecting …',
-'Rank updated redirect' => 'Rank updated. Redirecting …',
-'Rank removed redirect' => 'Rank removed. Redirecting …',
-'Ranks head' => 'Ranks',
-'Add rank subhead' => 'Add rank',
-'Add rank info' => 'Enter a rank and the minimum number of posts a user must have made to attain the rank. Different ranks cannot have the same value for minimum posts. If a title is set for a user, the title will be displayed instead of any rank. User ranks must be enabled in %s for this to have any effect.',
-'Rank title label' => 'Rank title',
-'Minimum posts label' => 'Minimum posts',
-'Actions label' => 'Actions',
-'Edit remove subhead' => 'Edit/remove ranks',
-'No ranks in list' => 'No ranks in list',
-
-);
diff --git a/upload/lang/English/admin_reports.php b/upload/lang/English/admin_reports.php
deleted file mode 100644
index f954fff..0000000
--- a/upload/lang/English/admin_reports.php
+++ /dev/null
@@ -1,21 +0,0 @@
- 'Report zapped. Redirecting …',
-'New reports head' => 'New reports',
-'Deleted user' => 'Deleted user',
-'Deleted' => 'Deleted',
-'Report subhead' => 'Reported %s',
-'Location seperator' => ' » ',
-'Reported by' => 'Reported by %s',
-'Reason' => 'Reason',
-'Zap' => 'Zap',
-'No new reports' => 'There are no new reports.',
-'Last 10 head' => '10 last zapped reports',
-'NA' => 'N/A',
-'Zapped subhead' => 'Zapped %s by %s',
-'No zapped reports' => 'There are no zapped reports.',
-
-);
diff --git a/upload/lang/English/admin_users.php b/upload/lang/English/admin_users.php
deleted file mode 100644
index 1e21a34..0000000
--- a/upload/lang/English/admin_users.php
+++ /dev/null
@@ -1,70 +0,0 @@
- 'You entered a non-numeric value into a numeric only column.',
-'Invalid date time message' => 'You entered an invalid date/time.',
-'Not verified' => 'Not verified',
-'User search head' => 'User search',
-'User search subhead' => 'Enter search criteria',
-'User search info' => 'Search for users in the database. You can enter one or more terms to search for. Wildcards in the form of asterisks (*) are accepted.',
-'Username label' => 'Username',
-'E-mail address label' => 'Email address',
-'Title label' => 'Title',
-'Real name label' => 'Real name',
-'Website label' => 'Website',
-'Jabber label' => 'Jabber',
-'ICQ label' => 'ICQ',
-'MSN label' => 'MSN Messenger',
-'AOL label' => 'AOL IM',
-'Yahoo label' => 'Yahoo Messenger',
-'Location label' => 'Location',
-'Signature label' => 'Signature',
-'Admin note label' => 'Admin note',
-'Posts more than label' => 'Number of posts greater than',
-'Posts less than label' => 'Number of posts less than',
-'Last post after label' => 'Last post is after',
-'Date help' => '(yyyy-mm-dd hh:mm:ss)',
-'Last post before label' => 'Last post is before',
-'Registered after label' => 'Registered after',
-'Registered before label' => 'Registered before',
-'Order by label' => 'Order by',
-'Order by username' => 'Username',
-'Order by e-mail' => 'Email',
-'Order by posts' => 'Number of posts',
-'Order by last post' => 'Last post',
-'Order by registered' => 'Registered',
-'Ascending' => 'Ascending',
-'Descending' => 'Descending',
-'User group label' => 'User group',
-'All groups' => 'All groups',
-'Unverified users' => 'Unverified users',
-'Submit search' => 'Submit search',
-'IP search head' => 'IP search',
-'IP search subhead' => 'Enter IP to search for',
-'IP address label' => 'IP address',
-'IP address help' => 'The IP address to search for in the post database.',
-'Find IP address' => 'Find IP address',
-
-'Results head' => 'Search Results',
-'Results username head' => 'Username',
-'Results e-mail head' => 'Email',
-'Results title head' => 'Title/Status',
-'Results posts head' => 'Posts',
-'Results admin note head' => 'Admin note',
-'Results actions head' => 'Actions',
-'Results IP address head' => 'IP address',
-'Results last used head' => 'Last used',
-'Results times found head' => 'Times found',
-'Results action head' => 'Action',
-'Results find more link' => 'Find more users for this ip',
-'Results no posts found' => 'There are currently no posts by that user in the forum.',
-'Bad IP message' => 'The supplied IP address is not correctly formatted.',
-'Results view IP link' => 'View IP stats',
-'Results show posts link' => 'Show posts',
-'Results guest' => 'Guest',
-'Results no IP found' => 'The supplied IP address could not be found in the database.',
-'No match' => 'No match'
-
-);
diff --git a/upload/lang/English/common.php b/upload/lang/English/common.php
deleted file mode 100644
index aaade9a..0000000
--- a/upload/lang/English/common.php
+++ /dev/null
@@ -1,191 +0,0 @@
- 'ltr', // ltr (Left-To-Right) or rtl (Right-To-Left)
-'lang_identifier' => 'en',
-
-// Number formatting
-'lang_decimal_point' => '.',
-'lang_thousands_sep' => ',',
-
-// Notices
-'Bad request' => 'Bad request. The link you followed is incorrect or outdated.',
-'No view' => 'You do not have permission to view these forums.',
-'No permission' => 'You do not have permission to access this page.',
-'Bad referrer' => 'Bad HTTP_REFERER. You were referred to this page from an unauthorized source. If the problem persists please make sure that \'Base URL\' is correctly set in Admin/Options and that you are visiting the forum by navigating to that URL. More information regarding the referrer check can be found in the FluxBB documentation.',
-'No cookie' => 'You appear to have logged in successfully, however a cookie has not been set. Please check your settings and if applicable, enable cookies for this website.',
-'Pun include error' => 'Unable to process user include %s from template %s. There is no such file in %s.',
-
-// Miscellaneous
-'Announcement' => 'Announcement',
-'Options' => 'Options',
-'Submit' => 'Submit', // "Name" of submit buttons
-'Ban message' => 'You are banned from this forum.',
-'Ban message 2' => 'The ban expires at the end of',
-'Ban message 3' => 'The administrator or moderator that banned you left the following message:',
-'Ban message 4' => 'Please direct any inquiries to the forum administrator at',
-'Never' => 'Never',
-'Today' => 'Today',
-'Yesterday' => 'Yesterday',
-'Info' => 'Info', // A common table header
-'Go back' => 'Go back',
-'Maintenance' => 'Maintenance',
-'Redirecting' => 'Redirecting',
-'Click redirect' => 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you)',
-'on' => 'on', // As in "BBCode is on"
-'off' => 'off',
-'Invalid email' => 'The email address you entered is invalid.',
-'Required' => '(Required)',
-'required field' => 'is a required field in this form.', // For javascript form validation
-'Last post' => 'Last post',
-'by' => 'by', // As in last post by someuser
-'New posts' => 'New posts', // The link that leads to the first new post
-'New posts info' => 'Go to the first new post in this topic.', // The popup text for new posts links
-'Username' => 'Username',
-'Password' => 'Password',
-'Email' => 'Email',
-'Send email' => 'Send email',
-'Moderated by' => 'Moderated by',
-'Registered' => 'Registered',
-'Subject' => 'Subject',
-'Message' => 'Message',
-'Topic' => 'Topic',
-'Forum' => 'Forum',
-'Posts' => 'Posts',
-'Replies' => 'Replies',
-'Pages' => 'Pages:',
-'Page' => 'Page %s',
-'BBCode' => 'BBCode:', // You probably shouldn't change this
-'img tag' => '[img] tag:',
-'Smilies' => 'Smilies:',
-'and' => 'and',
-'Image link' => 'image', // This is displayed (i.e. ) instead of images when "Show images" is disabled in the profile
-'wrote' => 'wrote:', // For [quote]'s
-'Mailer' => 'Mailer', // As in "MyForums Mailer" in the signature of outgoing emails
-'Important information' => 'Important information',
-'Write message legend' => 'Write your message and submit',
-'Previous' => 'Previous',
-'Next' => 'Next',
-'Spacer' => '…', // Ellipsis for paginate
-
-// Title
-'Title' => 'Title',
-'Member' => 'Member', // Default title
-'Moderator' => 'Moderator',
-'Administrator' => 'Administrator',
-'Banned' => 'Banned',
-'Guest' => 'Guest',
-
-// Stuff for include/parser.php
-'BBCode error no opening tag' => '[/%1$s] was found without a matching [%1$s]',
-'BBCode error invalid nesting' => '[%1$s] was opened within [%2$s], this is not allowed',
-'BBCode error invalid self-nesting' => '[%s] was opened within itself, this is not allowed',
-'BBCode error no closing tag' => '[%1$s] was found without a matching [/%1$s]',
-'BBCode error empty attribute' => '[%s] tag had an empty attribute section',
-'BBCode code problem' => 'There is a problem with your [code] tags',
-'BBCode list size error' => 'Your list was too long to parse, please make it smaller!',
-
-// Stuff for the navigator (top of every page)
-'Index' => 'Index',
-'User list' => 'User list',
-'Rules' => 'Rules',
-'Search' => 'Search',
-'Register' => 'Register',
-'Login' => 'Login',
-'Not logged in' => 'You are not logged in.',
-'Profile' => 'Profile',
-'Logout' => 'Logout',
-'Logged in as' => 'Logged in as',
-'Admin' => 'Administration',
-'Last visit' => 'Last visit: %s',
-'Show new posts' => 'Show new posts since last visit',
-'Mark all as read' => 'Mark all topics as read',
-'Mark forum read' => 'Mark this forum as read',
-'Title separator' => ' / ',
-
-// Stuff for the page footer
-'Board footer' => 'Board footer',
-'Search links' => 'Search links',
-'Show recent posts' => 'Show recent posts',
-'Show unanswered posts' => 'Show unanswered posts',
-'Show your posts' => 'Show your posts',
-'Show subscriptions' => 'Show your subscribed topics',
-'Jump to' => 'Jump to',
-'Go' => ' Go ', // Submit button in forum jump
-'Moderate topic' => 'Moderate topic',
-'Move topic' => 'Move topic',
-'Open topic' => 'Open topic',
-'Close topic' => 'Close topic',
-'Unstick topic' => 'Unstick topic',
-'Stick topic' => 'Stick topic',
-'Moderate forum' => 'Moderate forum',
-'Powered by' => 'Powered by %s',
-
-// Debug information
-'Debug table' => 'Debug information',
-'Querytime' => 'Generated in %1$s seconds, %2$s queries executed',
-'Query times' => 'Time (s)',
-'Query' => 'Query',
-'Total query time' => 'Total query time: %s',
-
-// Email related notifications
-'New user notification' => 'Alert - New registration',
-'New user message' => 'User \'%s\' registered in the forums at %s',
-'Banned email notification' => 'Alert - Banned email detected',
-'Banned email register message' => 'User \'%s\' registered with banned email address: %s',
-'Banned email change message' => 'User \'%s\' changed to banned email address: %s',
-'Banned email post message' => 'User \'%s\' posted with banned email address: %s',
-'Duplicate email notification' => 'Alert - Duplicate email detected',
-'Duplicate email register message' => 'User \'%s\' registered with an email address that also belongs to: %s',
-'Duplicate email change message' => 'User \'%s\' changed to an email address that also belongs to: %s',
-'Report notification' => 'Report(%d) - \'%s\'',
-'Report message 1' => 'User \'%s\' has reported the following message: %s',
-'Report message 2' => 'Reason: %s',
-
-'User profile' => 'User profile: %s',
-'Post URL' => 'Post URL: %s',
-'Email signature' => 'Forum Mailer'."\n".'(Do not reply to this message)',
-
-// For extern.php RSS feed
-'RSS description' => 'The most recent topics at %s.',
-'RSS description topic' => 'The most recent posts in %s.',
-'RSS reply' => 'Re: ', // The topic subject will be appended to this string (to signify a reply)
-'RSS active topics feed' => 'RSS active topics feed',
-'Atom active topics feed' => 'Atom active topics feed',
-'RSS forum feed' => 'RSS forum feed',
-'Atom forum feed' => 'Atom forum feed',
-'RSS topic feed' => 'RSS topic feed',
-'Atom topic feed' => 'Atom topic feed',
-
-// Admin related stuff in the header
-'New reports' => 'There are new reports',
-'Maintenance mode enabled' => 'Maintenance mode is enabled!',
-
-);
diff --git a/upload/lang/English/delete.php b/upload/lang/English/delete.php
deleted file mode 100644
index 29f358b..0000000
--- a/upload/lang/English/delete.php
+++ /dev/null
@@ -1,13 +0,0 @@
- 'Delete post',
-'Warning' => 'Warning! If this is the first post in the topic, the whole topic will be deleted.',
-'Author' => 'Author: %s',
-'Delete' => 'Delete', // The submit button
-'Post del redirect' => 'Post deleted. Redirecting …',
-'Topic del redirect' => 'Topic deleted. Redirecting …'
-
-);
diff --git a/upload/lang/English/forum.php b/upload/lang/English/forum.php
deleted file mode 100644
index 241677f..0000000
--- a/upload/lang/English/forum.php
+++ /dev/null
@@ -1,13 +0,0 @@
- 'Post new topic',
-'Views' => 'Views',
-'Moved' => 'Moved:',
-'Sticky' => 'Sticky:',
-'Closed' => 'Closed:',
-'Empty forum' => 'Forum is empty.'
-
-);
diff --git a/upload/lang/English/help.php b/upload/lang/English/help.php
deleted file mode 100644
index 2f39682..0000000
--- a/upload/lang/English/help.php
+++ /dev/null
@@ -1,55 +0,0 @@
- 'Help',
-'produces' => 'produces',
-
-'BBCode' => 'BBCode',
-'BBCode info 1' => 'BBCode is a collection of formatting tags that are used to change the look of text in this forum. BBCode is based on the same principal as, and is very similar to, HTML. Below is a list of all the available BBCodes and instructions on how to use them.',
-'BBCode info 2' => 'Administrators have the ability to enable or disable BBCode. You can tell if BBCode is enabled or disabled out in the left margin whenever you post a message or edit your signature.',
-
-'Text style' => 'Text style',
-'Text style info' => 'The following tags change the appearance of text:',
-'Bold text' => 'Bold text',
-'Underlined text' => 'Underlined text',
-'Italic text' => 'Italic text',
-'Red text' => 'Red text',
-'Blue text' => 'Blue text',
-'Heading text' => 'Heading text',
-
-'Links and images' => 'Links and images',
-'Links info' => 'You can create links to other documents or to email addresses using the following tags:',
-'My email address' => 'My email address',
-'Images info' => 'If you want to display an image you can use the img tag. The text appearing after the "=" sign in the opening tag is used for the alt attribute and should be included whenever possible.',
-
-'Quotes' => 'Quotes',
-'Quotes info' => 'If you want to quote someone, you should use the quote tag.',
-'Quotes info 2' => 'If you don\'t want to quote anyone in particular, you can use the quote tag without specifying a name.',
-'Quote text' => 'This is the text i want to quote.',
-'produces quote box' => 'produces a quote box like this:',
-'quote note' => 'Note: If a username contains the characters [ or ] you can enclose it in quote marks.',
-
-'Code' => 'Code',
-'Code info' => 'When displaying source code you should make sure that you use the code tag. Text displayed with the code tag will use a monospaced font and will not be affected by other tags.',
-'Code text' => 'This is some code.',
-'produces code box' => 'produces a code box like this:',
-
-'Nested tags' => 'Nested tags',
-'Nested tags info' => 'BBCode can be nested to create more advanced formatting. For example:',
-'Bold, underlined text' => 'Bold, underlined text',
-
-'Lists' => 'Lists',
-'List info' => 'To create a list you can use the list tag. You can create 3 types of lists using the list tag.',
-'List text 1' => 'Example list item 1.',
-'List text 2' => 'Example list item 2.',
-'List text 3' => 'Example list item 3.',
-'produces list' => 'produces a bulleted list.',
-'produces decimal list' => 'produces a numbered list.',
-'produces alpha list' => 'produces an alphabetically labelled list.',
-
-'Smilies' => 'Smilies',
-'Smilies info' => 'If you like (and if it is enabled), the forum can convert a series of smilies to images representations of that smiley. This forum recognizes the following smilies and replaces them with images:'
-
-);
diff --git a/upload/lang/English/index.html b/upload/lang/English/index.html
deleted file mode 100644
index 89337b2..0000000
--- a/upload/lang/English/index.html
+++ /dev/null
@@ -1 +0,0 @@
-..
diff --git a/upload/lang/English/index.php b/upload/lang/English/index.php
deleted file mode 100644
index 0ed222a..0000000
--- a/upload/lang/English/index.php
+++ /dev/null
@@ -1,20 +0,0 @@
- 'Topics',
-'Link to' => 'Link to:', // As in "Link to: http://fluxbb.org/"
-'Empty board' => 'Board is empty.',
-'Newest user' => 'Newest registered user: %s',
-'Users online' => 'Registered users online: %s',
-'Guests online' => 'Guests online: %s',
-'No of users' => 'Total number of registered users: %s',
-'No of topics' => 'Total number of topics: %s',
-'No of posts' => 'Total number of posts: %s',
-'Online' => 'Online:', // As in "Online: User A, User B etc."
-'Board info' => 'Board information',
-'Board stats' => 'Board statistics',
-'User info' => 'User information'
-
-);
diff --git a/upload/lang/English/login.php b/upload/lang/English/login.php
deleted file mode 100644
index 244ee06..0000000
--- a/upload/lang/English/login.php
+++ /dev/null
@@ -1,26 +0,0 @@
- 'Wrong username and/or password.',
-'Forgotten pass' => 'Forgotten your password?',
-'Login redirect' => 'Logged in successfully. Redirecting …',
-'Logout redirect' => 'Logged out. Redirecting …',
-'No email match' => 'There is no user registered with the email address',
-'Request pass' => 'Request password',
-'Request pass legend' => 'Enter the email address with which you registered',
-'Request pass info' => 'A new password together with a link to activate the new password will be sent to that address.',
-'Not registered' => 'Not registered yet?',
-'Login legend' => 'Enter your username and password below',
-'Remember me' => 'Log me in automatically each time I visit.',
-'Login info' => 'If you have not registered or have forgotten your password click on the appropriate link below.',
-'New password errors' => 'Password request error',
-'New passworderrors info' => 'The following error needs to be corrected before a new password can be sent:',
-
-// Forget password mail stuff
-'Forget mail' => 'An email has been sent to the specified address with instructions on how to change your password. If it does not arrive you can contact the forum administrator at',
-'Email flood' => 'This account has already requested a password reset in the past hour. Please wait a while before requesting a new password again.'
-
-);
diff --git a/upload/lang/English/mail_templates/activate_email.tpl b/upload/lang/English/mail_templates/activate_email.tpl
deleted file mode 100644
index f17066f..0000000
--- a/upload/lang/English/mail_templates/activate_email.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-Subject: Change email address requested
-
-Hello ,
-
-You have requested to have a new email address assigned to your account in the discussion forum at . If you didn't request this or if you don't want to change your email address you should just ignore this message. Only if you visit the activation page below will your email address be changed. In order for the activation page to work, you must be logged in to the forum.
-
-To change your email address, please visit the following page:
-
-
---
-
-(Do not reply to this message)
diff --git a/upload/lang/English/mail_templates/activate_password.tpl b/upload/lang/English/mail_templates/activate_password.tpl
deleted file mode 100644
index 33b2b3e..0000000
--- a/upload/lang/English/mail_templates/activate_password.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-Subject: New password requested
-
-Hello ,
-
-You have requested to have a new password assigned to your account in the discussion forum at . If you didn't request this or if you don't want to change your password you should just ignore this message. Only if you visit the activation page below will your password be changed.
-
-Your new password is:
-
-To change your password, please visit the following page:
-
-
---
-
-(Do not reply to this message)
diff --git a/upload/lang/English/mail_templates/form_email.tpl b/upload/lang/English/mail_templates/form_email.tpl
deleted file mode 100644
index b862422..0000000
--- a/upload/lang/English/mail_templates/form_email.tpl
+++ /dev/null
@@ -1,13 +0,0 @@
-Subject:
-
- from has sent you a message. You can reply to by replying to this email.
-
-The message reads as follows:
------------------------------------------------------------------------
-
-
-
------------------------------------------------------------------------
-
---
-
diff --git a/upload/lang/English/mail_templates/index.html b/upload/lang/English/mail_templates/index.html
deleted file mode 100644
index 89337b2..0000000
--- a/upload/lang/English/mail_templates/index.html
+++ /dev/null
@@ -1 +0,0 @@
-..
diff --git a/upload/lang/English/mail_templates/new_reply.tpl b/upload/lang/English/mail_templates/new_reply.tpl
deleted file mode 100644
index e9dab0b..0000000
--- a/upload/lang/English/mail_templates/new_reply.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-Subject: Reply to topic:
-
- has replied to the topic to which you are subscribed. There may be more new replies, but this is the only notification you will receive until you visit the board again.
-
-The post is located at
-
-You can unsubscribe by going to
-
---
-
-(Do not reply to this message)
diff --git a/upload/lang/English/mail_templates/new_reply_full.tpl b/upload/lang/English/mail_templates/new_reply_full.tpl
deleted file mode 100644
index 7231145..0000000
--- a/upload/lang/English/mail_templates/new_reply_full.tpl
+++ /dev/null
@@ -1,18 +0,0 @@
-Subject: Reply to topic:
-
- has replied to the topic to which you are subscribed. There may be more new replies, but this is the only notification you will receive until you visit the board again.
-
-The message reads as follows:
------------------------------------------------------------------------
-
-
-
------------------------------------------------------------------------
-
-The post is located at
-
-You can unsubscribe by going to
-
---
-
-(Do not reply to this message)
diff --git a/upload/lang/English/mail_templates/welcome.tpl b/upload/lang/English/mail_templates/welcome.tpl
deleted file mode 100644
index 0110042..0000000
--- a/upload/lang/English/mail_templates/welcome.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-Subject: Welcome to !
-
-Thank you for registering in the forums at . Your account details are:
-
-Username:
-Password:
-
-Login at to activate the account.
-
---
-
-(Do not reply to this message)
diff --git a/upload/lang/English/misc.php b/upload/lang/English/misc.php
deleted file mode 100644
index 9ccd4b2..0000000
--- a/upload/lang/English/misc.php
+++ /dev/null
@@ -1,90 +0,0 @@
- 'All topics and forums have been marked as read. Redirecting …',
-'Mark forum read redirect' => 'All topics in the specified forum have been marked as read. Redirecting …',
-
-// Send email
-'Form email disabled' => 'The user you are trying to send an email to has disabled form email.',
-'No email subject' => 'You must enter a subject.',
-'No email message' => 'You must enter a message.',
-'Too long email message' => 'Messages cannot be longer than 65535 characters (64 KB).',
-'Email flood' => 'At least %s seconds have to pass between sent emails. Please wait a while and try sending again.',
-'Email sent redirect' => 'Email sent. Redirecting …',
-'Send email to' => 'Send email to',
-'Email subject' => 'Subject',
-'Email message' => 'Message',
-'Email disclosure note' => 'Please note that by using this form, your email address will be disclosed to the recipient.',
-'Write email' => 'Write and submit your email message',
-
-// Report
-'No reason' => 'You must enter a reason.',
-'Report flood' => 'At least %s seconds have to pass between reports. Please wait a while and try sending again.',
-'Report redirect' => 'Post reported. Redirecting …',
-'Report post' => 'Report post',
-'Reason' => 'Reason',
-'Reason desc' => 'Please enter a short reason why you are reporting this post',
-
-// Subscriptions
-'Already subscribed' => 'You are already subscribed to this topic.',
-'Subscribe redirect' => 'Your subscription has been added. Redirecting …',
-'Not subscribed' => 'You are not subscribed to this topic.',
-'Unsubscribe redirect' => 'Your subscription has been removed. Redirecting …',
-
-// General forum and topic moderation
-'Moderate' => 'Moderate',
-'Select' => 'Select', // the header of a column of checkboxes
-'Move' => 'Move',
-'Split' => 'Split',
-'Delete' => 'Delete',
-'Merge' => 'Merge',
-
-// Moderate forum
-'Open' => 'Open',
-'Close' => 'Close',
-'Move topic' => 'Move topic',
-'Move topics' => 'Move topics',
-'Move legend' => 'Select destination of move',
-'Move to' => 'Move to',
-'Nowhere to move' => 'There are no forums into which you can move topics.',
-'Leave redirect' => 'Leave redirect topic(s)',
-'Move topic redirect' => 'Topic moved. Redirecting …',
-'Move topics redirect' => 'Topics moved. Redirecting …',
-'Confirm delete legend' => 'Please confirm deletion',
-'Delete topics' => 'Delete topics',
-'Delete topics comply' => 'Are you sure you want to delete the selected topics?',
-'Delete topics redirect' => 'Topics deleted. Redirecting …',
-'Open topic redirect' => 'Topic opened. Redirecting …',
-'Open topics redirect' => 'Topics opened. Redirecting …',
-'Close topic redirect' => 'Topic closed. Redirecting …',
-'Close topics redirect' => 'Topics closed. Redirecting …',
-'No topics selected' => 'You must select at least one topic for move/delete/open/close.',
-'Not enough topics selected' => 'You must select at least two topics for merge.',
-'Stick topic redirect' => 'Topic sticked. Redirecting …',
-'Unstick topic redirect' => 'Topic unsticked. Redirecting …',
-'Merge topics' => 'Merge topics',
-'Merge topics redirect' => 'Topics merged. Redirecting …',
-'Confirm merge legend' => 'Please confirm merge',
-'New subject' => 'New subject',
-
-// Split multiple posts in topic
-'Confirm split legend' => 'Please confirm split of selected posts.',
-'Split posts' => 'Split posts',
-'Split posts comply' => 'Are you sure you want to split the selected posts?',
-'Split posts redirect' => 'Posts have been split. Redirecting …',
-
-// Delete multiple posts in topic
-'Delete posts' => 'Delete posts',
-'Cannot select first' => 'First post cannot be selected for split/delete.',
-'Delete posts comply' => 'Are you sure you want to delete the selected posts?',
-'Delete posts redirect' => 'Posts deleted. Redirecting …',
-'No posts selected' => 'You must select at least one post for split/delete.',
-
-// Get host
-'Host info 1' => 'The IP address is: %s',
-'Host info 2' => 'The host name is: %s',
-'Show more users' => 'Show more users for this IP',
-
-);
diff --git a/upload/lang/English/post.php b/upload/lang/English/post.php
deleted file mode 100644
index 5c8ea37..0000000
--- a/upload/lang/English/post.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'Topics must contain a subject.',
-'Too long subject' => 'Subjects cannot be longer than 70 characters.',
-'No message' => 'You must enter a message.',
-'Too long message' => 'Posts cannot be longer that 65535 characters (64 KB).',
-'All caps subject' => 'Subjects cannot contain only capital letters.',
-'All caps message' => 'Posts cannot contain only capital letters.',
-
-// Posting
-'Post errors' => 'Post errors',
-'Post errors info' => 'The following errors need to be corrected before the message can be posted:',
-'Post preview' => 'Post preview',
-'Guest name' => 'Name', // For guests (instead of Username)
-'Post redirect' => 'Post entered. Redirecting …',
-'Post a reply' => 'Post a reply',
-'Post new topic' => 'Post new topic',
-'Hide smilies' => 'Never show smilies as icons for this post',
-'Subscribe' => 'Subscribe to this topic',
-'Stay subscribed' => 'Stay subscribed to this topic',
-'Topic review' => 'Topic review (newest first)',
-'Flood start' => 'At least',
-'flood end' => 'seconds have to pass between posts. Please wait a little while and try posting again.',
-'Preview' => 'Preview', // submit button to preview message
-
-// Edit post
-'Edit post legend' => 'Edit the post and submit changes',
-'Silent edit' => 'Silent edit (don\'t display "Edited by ..." in topic view)',
-'Edit post' => 'Edit post',
-'Edit redirect' => 'Post updated. Redirecting …'
-
-);
diff --git a/upload/lang/English/prof_reg.php b/upload/lang/English/prof_reg.php
deleted file mode 100644
index 9a69b41..0000000
--- a/upload/lang/English/prof_reg.php
+++ /dev/null
@@ -1,81 +0,0 @@
- 'Enter a valid email address',
-'Email legend 2' => 'Enter and confirm a valid email address',
-'Localisation legend' => 'Set your localisation options',
-'Time zone' => 'Time zone',
-'Time zone info' => 'For the forum to display times correctly you must select your local time zone. If Daylight Savings Time is in effect you should also check the option provided which will advance times by 1 hour.',
-'DST' => 'Daylight Savings Time is in effect (advance time by 1 hour).',
-'Time format' => 'Time format',
-'Date format' => 'Date format',
-'Default' => 'Default',
-'Language' => 'Language',
-'Email setting info' => 'Select whether you want your email address to be viewable to other users or not and if you want other users to be able to send you email via the forum (form email) or not.',
-'Email setting 1' => 'Display your email address.',
-'Email setting 2' => 'Hide your email address but allow form email.',
-'Email setting 3' => 'Hide your email address and disallow form email.',
-'Privacy options legend' => 'Set your privacy options',
-'Confirm pass' => 'Confirm password',
-
-'Username too short' => 'Usernames must be at least 2 characters long. Please choose another (longer) username.',
-'Username too long' => 'Usernames must not be more than 25 characters long. Please choose another (shorter) username.',
-'Username guest' => 'The username guest is reserved. Please choose another username.',
-'Username IP' => 'Usernames may not be in the form of an IP address. Please choose another username.',
-'Username reserved chars' => 'Usernames may not contain all the characters \', " and [ or ] at once. Please choose another username.',
-'Username BBCode' => 'Usernames may not contain any of the text formatting tags (BBCode) that the forum uses. Please choose another username.',
-'Banned username' => 'The username you entered is banned in this forum. Please choose another username.',
-'Pass too short' => 'Passwords must be at least 4 characters long. Please choose another (longer) password.',
-'Pass not match' => 'Passwords do not match.',
-'Banned email' => 'The email address you entered is banned in this forum. Please choose another email address.',
-'Dupe email' => 'Someone else is already registered with that email address. Please choose another email address.',
-'Sig too long' => 'Signatures cannot be longer than',
-'characters' => 'characters',
-'Sig too many lines' => 'Signatures cannot have more than',
-'lines' => 'lines',
-'Bad ICQ' => 'You entered an invalid ICQ UIN. Please go back and correct.',
-
-'UTC-12:00' => '(UTC-12:00) International Date Line West',
-'UTC-11:00' => '(UTC-11:00) Niue, Samoa',
-'UTC-10:00' => '(UTC-10:00) Hawaii-Aleutian, Cook Island',
-'UTC-09:30' => '(UTC-09:30) Marquesas Islands',
-'UTC-09:00' => '(UTC-09:00) Alaska, Gambier Island',
-'UTC-08:30' => '(UTC-08:30) Pitcairn Islands',
-'UTC-08:00' => '(UTC-08:00) Pacific',
-'UTC-07:00' => '(UTC-07:00) Mountain',
-'UTC-06:00' => '(UTC-06:00) Central',
-'UTC-05:00' => '(UTC-05:00) Eastern',
-'UTC-04:00' => '(UTC-04:00) Atlantic',
-'UTC-03:30' => '(UTC-03:30) Newfoundland',
-'UTC-03:00' => '(UTC-03:00) Amazon, Central Greenland',
-'UTC-02:00' => '(UTC-02:00) Mid-Atlantic',
-'UTC-01:00' => '(UTC-01:00) Azores, Cape Verde, Eastern Greenland',
-'UTC' => '(UTC) Western European, Greenwich',
-'UTC+01:00' => '(UTC+01:00) Central European, West African',
-'UTC+02:00' => '(UTC+02:00) Eastern European, Central African',
-'UTC+03:00' => '(UTC+03:00) Moscow, Eastern African',
-'UTC+03:30' => '(UTC+03:30) Iran',
-'UTC+04:00' => '(UTC+04:00) Gulf, Samara',
-'UTC+04:30' => '(UTC+04:30) Afghanistan',
-'UTC+05:00' => '(UTC+05:00) Pakistan, Yekaterinburg',
-'UTC+05:30' => '(UTC+05:30) India, Sri Lanka',
-'UTC+05:45' => '(UTC+05:45) Nepal',
-'UTC+06:00' => '(UTC+06:00) Bangladesh, Bhutan, Novosibirsk',
-'UTC+06:30' => '(UTC+06:30) Cocos Islands, Myanmar',
-'UTC+07:00' => '(UTC+07:00) Indochina, Krasnoyarsk',
-'UTC+08:00' => '(UTC+08:00) Greater China, Australian Western, Irkutsk',
-'UTC+08:45' => '(UTC+08:45) Southeastern Western Australia',
-'UTC+09:00' => '(UTC+09:00) Japan, Korea, Chita',
-'UTC+09:30' => '(UTC+09:30) Australian Central',
-'UTC+10:00' => '(UTC+10:00) Australian Eastern, Vladivostok',
-'UTC+10:30' => '(UTC+10:30) Lord Howe',
-'UTC+11:00' => '(UTC+11:00) Solomon Island, Magadan',
-'UTC+11:30' => '(UTC+11:30) Norfolk Island',
-'UTC+12:00' => '(UTC+12:00) New Zealand, Fiji, Kamchatka',
-'UTC+12:45' => '(UTC+12:45) Chatham Islands',
-'UTC+13:00' => '(UTC+13:00) Tonga, Phoenix Islands',
-'UTC+14:00' => '(UTC+14:00) Line Islands'
-
-);
diff --git a/upload/lang/English/profile.php b/upload/lang/English/profile.php
deleted file mode 100644
index ef6a98c..0000000
--- a/upload/lang/English/profile.php
+++ /dev/null
@@ -1,140 +0,0 @@
- 'Profile menu',
-'Section essentials' => 'Essentials',
-'Section personal' => 'Personal',
-'Section messaging' => 'Messaging',
-'Section personality' => 'Personality',
-'Section display' => 'Display',
-'Section privacy' => 'Privacy',
-'Section admin' => 'Administration',
-
-// Miscellaneous
-'Username and pass legend' => 'Enter your username and password',
-'Personal details legend' => 'Enter your personal details',
-'Contact details legend' => 'Enter your messaging details',
-'User activity' => 'User activity',
-'Paginate info' => 'Enter the number of topics and posts you wish to view on each page.',
-
-// Password stuff
-'Pass key bad' => 'The specified password activation key was incorrect or has expired. Please re-request a new password. If that fails, contact the forum administrator at',
-'Pass updated' => 'Your password has been updated. You can now login with your new password.',
-'Pass updated redirect' => 'Password updated. Redirecting …',
-'Wrong pass' => 'Wrong old password.',
-'Change pass' => 'Change password',
-'Change pass legend' => 'Enter and confirm your new password',
-'Old pass' => 'Old password',
-'New pass' => 'New password',
-'Confirm new pass' => 'Confirm new password',
-'Pass info' => 'Passwords must be at least 4 characters long. Passwords are case sensitive.',
-
-// Email stuff
-'Email key bad' => 'The specified email activation key was incorrect or has expired. Please re-request change of email address. If that fails, contact the forum administrator at',
-'Email updated' => 'Your email address has been updated.',
-'Activate email sent' => 'An email has been sent to the specified address with instructions on how to activate the new email address. If it doesn\'t arrive you can contact the forum administrator at',
-'Email legend' => 'Enter your new email address',
-'Email instructions' => 'An email will be sent to your new address with an activation link. You must click the link in the email you receive to activate the new address.',
-'Change email' => 'Change email address',
-'New email' => 'New email',
-
-// Avatar upload stuff
-'Avatars disabled' => 'The administrator has disabled avatar support.',
-'Too large ini' => 'The selected file was too large to upload. The server didn\'t allow the upload.',
-'Partial upload' => 'The selected file was only partially uploaded. Please try again.',
-'No tmp directory' => 'PHP was unable to save the uploaded file to a temporary location.',
-'No file' => 'You did not select a file for upload.',
-'Bad type' => 'The file you tried to upload is not of an allowed type. Allowed types are gif, jpeg and png.',
-'Too wide or high' => 'The file you tried to upload is wider and/or higher than the maximum allowed',
-'Too large' => 'The file you tried to upload is larger than the maximum allowed',
-'pixels' => 'pixels',
-'bytes' => 'bytes',
-'Move failed' => 'The server was unable to save the uploaded file. Please contact the forum administrator at',
-'Unknown failure' => 'An unknown error occurred. Please try again.',
-'Avatar upload redirect' => 'Avatar uploaded. Redirecting …',
-'Avatar deleted redirect' => 'Avatar deleted. Redirecting …',
-'Avatar desc' => 'An avatar is a small image that will be displayed under your username in your posts. It must not be any bigger than',
-'Upload avatar' => 'Upload avatar',
-'Upload avatar legend' => 'Enter an avatar file to upload',
-'Delete avatar' => 'Delete avatar', // only for admins
-'File' => 'File',
-'Upload' => 'Upload', // submit button
-
-// Form validation stuff
-'Forbidden title' => 'The title you entered contains a forbidden word. You must choose a different title.',
-'Profile redirect' => 'Profile updated. Redirecting …',
-
-// Profile display stuff
-'Users profile' => '%s\'s profile',
-'Unknown' => '(Unknown)', // This is displayed when a user hasn't filled out profile field (e.g. Location)
-'Private' => '(Private)', // This is displayed when a user does not want to receive emails
-'No avatar' => '(No avatar)',
-'Username info' => 'Username: %s',
-'Email info' => 'Email: %s',
-'Posts info' => 'Posts: %s',
-'Registered info' => 'Registered: %s',
-'Last post info' => 'Last post: %s',
-'Show posts' => 'Show all posts',
-'Realname' => 'Real name',
-'Location' => 'Location',
-'Website' => 'Website',
-'Jabber' => 'Jabber',
-'ICQ' => 'ICQ',
-'MSN' => 'MSN Messenger',
-'AOL IM' => 'AOL IM',
-'Yahoo' => 'Yahoo! Messenger',
-'Avatar' => 'Avatar',
-'Signature' => 'Signature',
-'Sig max size' => 'Max length: %s characters / Max lines: %s',
-'Avatar legend' => 'Set your avatar display options',
-'Avatar info' => 'An avatar is a small image that will be displayed with all your posts. You can upload an avatar by clicking the link below.',
-'Change avatar' => 'Change avatar',
-'Signature legend' => 'Compose your signature',
-'Signature info' => 'A signature is a small piece of text that is attached to your posts. In it, you can enter just about anything you like. Perhaps you would like to enter your favourite quote or your star sign. It\'s up to you! In your signature you can use BBCode if it is allowed in this particular forum. You can see the features that are allowed/enabled listed below whenever you edit your signature.',
-'Sig preview' => 'Current signature preview:',
-'No sig' => 'No signature currently stored in profile.',
-'Signature quote/code/list/h' => 'The quote, code, list, and heading BBCodes are not allowed in signatures.',
-'Topics per page' => 'Topics',
-'Posts per page' => 'Posts',
-'Leave blank' => 'Leave blank to use forum default.',
-'Subscription legend' => 'Set your subscription options',
-'Notify full' => 'Include a plain text version of new posts in subscription notification emails.',
-'Auto notify full' => 'Automatically subscribe to every topic you post in.',
-'Show smilies' => 'Show smilies as graphic icons.',
-'Show images' => 'Show images in posts.',
-'Show images sigs' => 'Show images in user signatures.',
-'Show avatars' => 'Show user avatars in posts.',
-'Show sigs' => 'Show user signatures.',
-'Style legend' => 'Select your preferred style',
-'Styles' => 'Styles',
-'Admin note' => 'Admin note',
-'Pagination legend' => 'Enter your pagination options',
-'Post display legend' => 'Set your options for viewing posts',
-'Post display info' => 'If you are on a slow connection, disabling these options, particularly showing images in posts and signatures, will make pages load faster.',
-'Instructions' => 'When you update your profile, you will be redirected back to this page.',
-
-// Administration stuff
-'Group membership legend' => 'Choose user group',
-'Save' => 'Save',
-'Set mods legend' => 'Set moderator access',
-'Moderator in info' => 'Choose which forums this user should be allowed to moderate. Note: This only applies to moderators. Administrators always have full permissions in all forums.',
-'Update forums' => 'Update forums',
-'Delete ban legend' => 'Delete (administrators only) or ban user',
-'Delete user' => 'Delete user',
-'Ban user' => 'Ban user',
-'Confirm delete legend' => 'Important: read before deleting user',
-'Confirm delete user' => 'Confirm delete user',
-'Confirmation info' => 'Please confirm that you want to delete the user', // the username will be appended to this string
-'Delete warning' => 'Warning! Deleted users and/or posts cannot be restored. If you choose not to delete the posts made by this user, the posts can only be deleted manually at a later time.',
-'Delete posts' => 'Delete any posts and topics this user has made.',
-'Delete' => 'Delete', // submit button (confirm user delete)
-'User delete redirect' => 'User deleted. Redirecting …',
-'Group membership redirect' => 'Group membership saved. Redirecting …',
-'Update forums redirect' => 'Forum moderator rights updated. Redirecting …',
-'Ban redirect' => 'Redirecting …',
-'No delete admin message' => 'Administrators cannot be deleted. In order to delete this user, you must first move him/her to a different user group.',
-
-);
diff --git a/upload/lang/English/register.php b/upload/lang/English/register.php
deleted file mode 100644
index c3e24df..0000000
--- a/upload/lang/English/register.php
+++ /dev/null
@@ -1,37 +0,0 @@
- 'This forum is not accepting new registrations.',
-'Reg cancel redirect' => 'Registration cancelled. Redirecting …',
-'Forum rules' => 'Forum rules',
-'Rules legend' => 'You must agree to the following in order to register',
-'Registration flood' => 'A new user was registered with the same IP address as you within the last hour. To prevent registration flooding, at least an hour has to pass between registrations from the same IP. Sorry for the inconvenience.',
-'Agree' => 'Agree',
-'Cancel' => 'Cancel',
-'Register' => 'Register',
-
-// Form validation stuff (some of these are also used in post.php)
-'Registration errors' => 'Registration errors',
-'Registration errors info' => 'The following errors need to be corrected before you can register:',
-'Username censor' => 'The username you entered contains one or more censored words. Please choose a different username.',
-'Username dupe 1' => 'Someone is already registered with the username',
-'Username dupe 2' => 'The username you entered is too similar. The username must differ from that by at least one alphanumerical character (a-z or 0-9). Please choose a different username.',
-'Email not match' => 'Email addresses do not match.',
-
-// Registration email stuff
-'Reg email' => 'Thank you for registering. Your password has been sent to the specified address. If it doesn\'t arrive you can contact the forum administrator at',
-'Reg complete' => 'Registration complete. Logging in and redirecting …',
-
-// Register info
-'Desc 1' => 'Registration will grant you access to a number of features and capabilities otherwise unavailable. These functions include the ability to edit and delete posts, design your own signature that accompanies your posts and much more. If you have any questions regarding this forum you should ask an administrator.',
-'Desc 2' => 'Below is a form you must fill out in order to register. Once you are registered you should visit your profile and review the different settings you can change. The fields below only make up a small part of all the settings you can alter in your profile.',
-'Username legend' => 'Please enter a username between 2 and 25 characters long',
-'Pass legend' => 'Please enter and confirm your chosen password',
-'Pass info' => 'Passwords must be at least 4 characters long. Passwords are case sensitive.',
-'Email info' => 'You must enter a valid email address as your randomly generated password will be sent to that address.',
-'Confirm email' => 'Confirm email address',
-
-);
diff --git a/upload/lang/English/search.php b/upload/lang/English/search.php
deleted file mode 100644
index d6a5081..0000000
--- a/upload/lang/English/search.php
+++ /dev/null
@@ -1,49 +0,0 @@
- 'User search',
-'No search permission' => 'You do not have permission to use the search feature.',
-'Search flood' => 'At least %s seconds have to pass between searches. Please wait a while and try searching again.',
-'Search' => 'Search',
-'Search criteria legend' => 'Enter your search criteria',
-'Search info' => 'To search by keyword, enter a term or terms to search for. Separate terms with spaces. Use AND, OR and NOT to refine your search. To search by author enter the username of the author whose posts you wish to search for. Use wildcard character * for partial matches.',
-'Keyword search' => 'Keyword search',
-'Author search' => 'Author search',
-'Search in legend' => 'Select where to search',
-'Search in info' => 'Choose in which forum you would