A contentious decision has seen the ability to include PHP within the template introduced. This is achieved by enclosing the PHP within relevant tags:
@@ -2252,12 +2330,71 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
+
+
+
+
Revision 10007
+
+
+
+
Revision 9817
+
+
Revision 8732
@@ -2330,7 +2467,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
-
8. Copyright and disclaimer
+
9. Copyright and disclaimer
diff --git a/phpBB/docs/hook_system.html b/phpBB/docs/hook_system.html
index 565e0096fc..b23ebab869 100644
--- a/phpBB/docs/hook_system.html
+++ b/phpBB/docs/hook_system.html
@@ -104,14 +104,14 @@ h3 {
border-top: 1px solid #ccc;
}
-code {
- color: #006600;
- font-weight: normal;
- font-family: 'Courier New', monospace;
- border-color: #D1D7DC;
- border-width: 1px;
- border-style: solid;
- background-color: #FAFAFA;
+code {
+ color: #006600;
+ font-weight: normal;
+ font-family: 'Courier New', monospace;
+ border-color: #D1D7DC;
+ border-width: 1px;
+ border-style: solid;
+ background-color: #FAFAFA;
}
#wrap {
@@ -387,8 +387,36 @@ PHPBB_MSG_HANDLER (overwrite message handler)
PHPBB_DB_NEW_LINK (overwrite new_link parameter for sql_connect)
PHPBB_ROOT_PATH (overwrite $phpbb_root_path)
PHPBB_ADMIN_PATH (overwrite $phpbb_admin_path)
+PHPBB_USE_BOARD_URL_PATH (use generate_board_url() for image paths instead of $phpbb_root_path)
+
If the PHPBB_USE_BOARD_URL_PATH
constant is set to true, phpBB uses generate_board_url() (this will return the boards url with the script path included) on all instances where web-accessible images are loaded. The exact locations are:
+
+
+ - /includes/session.php - user::img()
+ - /includes/functions_content.php - smiley_text()
+
+
+
Path locations for the following template variables are affected by this too:
+
+
+ - {T_THEME_PATH} - styles/xxx/theme
+ - {T_TEMPLATE_PATH} - styles/xxx/template
+ - {T_SUPER_TEMPLATE_PATH} - styles/xxx/template
+ - {T_IMAGESET_PATH} - styles/xxx/imageset
+ - {T_IMAGESET_LANG_PATH} - styles/xxx/imageset/yy
+ - {T_IMAGES_PATH} - images/
+ - {T_SMILIES_PATH} - $config['smilies_path']/
+ - {T_AVATAR_PATH} - $config['avatar_path']/
+ - {T_AVATAR_GALLERY_PATH} - $config['avatar_gallery_path']/
+ - {T_ICONS_PATH} - $config['icons_path']/
+ - {T_RANKS_PATH} - $config['ranks_path']/
+ - {T_UPLOAD_PATH} - $config['upload_path']/
+ - {T_STYLESHEET_LINK} - styles/xxx/theme/stylesheet.css (or link to style.php if css is parsed dynamically)
+ - New template variable {BOARD_URL} for the board url + script path.
+
+
+
@@ -616,7 +644,7 @@ echo $second_object->hook_me('first', 'second') . '<br />';
not hooked
-hooked
+hooked
A different possibility would be using a function variable (which could be left out on passing the function variables to the hook):
@@ -670,7 +698,7 @@ echo $second_object->hook_me('first', 'second') . '<br />';
not hooked
-hooked
+hooked
diff --git a/phpBB/download/file.php b/phpBB/download/file.php
index 32b5f87950..c6106fc09f 100644
--- a/phpBB/download/file.php
+++ b/phpBB/download/file.php
@@ -249,7 +249,7 @@ if (!$attachment)
trigger_error('ERROR_NO_ATTACHMENT');
}
-$attachment['physical_filename'] = basename($attachment['physical_filename']);
+$attachment['physical_filename'] = utf8_basename($attachment['physical_filename']);
$display_cat = $extensions[$attachment['extension']]['display_cat'];
if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
diff --git a/phpBB/faq.php b/phpBB/faq.php
index da064e4452..0a04bad8eb 100644
--- a/phpBB/faq.php
+++ b/phpBB/faq.php
@@ -38,15 +38,28 @@ switch ($mode)
}
// Pull the array data from the lang pack
+$switch_column = $found_switch = false;
$help_blocks = array();
foreach ($user->help as $help_ary)
{
if ($help_ary[0] == '--')
{
- $template->assign_block_vars('faq_block', array(
- 'BLOCK_TITLE' => $help_ary[1])
- );
+ if ($help_ary[1] == '--')
+ {
+ $switch_column = true;
+ $found_switch = true;
+ continue;
+ }
+ $template->assign_block_vars('faq_block', array(
+ 'BLOCK_TITLE' => $help_ary[1],
+ 'SWITCH_COLUMN' => $switch_column,
+ ));
+
+ if ($switch_column)
+ {
+ $switch_column = false;
+ }
continue;
}
@@ -58,11 +71,13 @@ foreach ($user->help as $help_ary)
// Lets build a page ...
$template->assign_vars(array(
- 'L_FAQ_TITLE' => $l_title,
- 'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'])
-);
+ 'L_FAQ_TITLE' => $l_title,
+ 'L_BACK_TO_TOP' => $user->lang['BACK_TO_TOP'],
-page_header($l_title);
+ 'SWITCH_COLUMN_MANUALLY' => (!$found_switch) ? true : false,
+));
+
+page_header($l_title, false);
$template->set_filenames(array(
'body' => 'faq_body.html')
diff --git a/phpBB/feed.php b/phpBB/feed.php
new file mode 100644
index 0000000000..9603b27301
--- /dev/null
+++ b/phpBB/feed.php
@@ -0,0 +1,1064 @@
+session_begin();
+$auth->acl($user->data);
+$user->setup();
+
+// Initial var setup
+$forum_id = request_var('f', 0);
+$topic_id = request_var('t', 0);
+$mode = request_var('mode', '');
+
+// Feed date format for PHP > 5 and PHP4
+$feed_date_format = (PHP_VERSION >= 5) ? 'c' : "Y-m-d\TH:i:sO";
+$params = false;
+
+// We do not use a template, therefore we simply define the global template variables here
+$global_vars = $item_vars = array();
+
+// Generate params array for use in append_sid() to correctly link back to this page
+if ($forum_id || $topic_id || $mode)
+{
+ $params = array(
+ 'f' => ($forum_id) ? $forum_id : NULL,
+ 't' => ($topic_id) ? $topic_id : NULL,
+ 'mode' => ($mode) ? $mode : NULL,
+ );
+}
+
+// This boards URL
+$board_url = generate_board_url();
+
+// Get correct feed object
+$feed = phpbb_feed_factory::init($mode, $forum_id, $topic_id);
+
+// No feed found
+if ($feed === false)
+{
+ trigger_error('NO_FEED');
+}
+
+// Open Feed
+$feed->open();
+
+// Some default assignments
+// FEED_IMAGE is not used (atom)
+$global_vars = array(
+ 'FEED_IMAGE' => ($user->img('site_logo', '', false, '', 'src')) ? $board_url . '/' . substr($user->img('site_logo', '', false, '', 'src'), strlen($phpbb_root_path)) : '',
+ 'SELF_LINK' => feed_append_sid('/feed.' . $phpEx, $params),
+ 'FEED_LINK' => $board_url . '/index.' . $phpEx,
+ 'FEED_TITLE' => $config['sitename'],
+ 'FEED_SUBTITLE' => $config['site_desc'],
+ 'FEED_UPDATED' => $user->format_date(time(), $feed_date_format, true),
+ 'FEED_LANG' => $user->lang['USER_LANG'],
+ 'FEED_AUTHOR' => $config['sitename'],
+);
+
+// Iterate through items
+while ($row = $feed->get_item())
+{
+ // BBCode options to correctly disable urls, smilies, bbcode...
+ if ($feed->get('options') === NULL)
+ {
+ // Allow all combinations
+ $options = 7;
+
+ if ($feed->get('enable_bbcode') !== NULL && $feed->get('enable_smilies') !== NULL && $feed->get('enable_magic_url') !== NULL)
+ {
+ $options = (($row[$feed->get('enable_bbcode')]) ? OPTION_FLAG_BBCODE : 0) + (($row[$feed->get('enable_smilies')]) ? OPTION_FLAG_SMILIES : 0) + (($row[$feed->get('enable_magic_url')]) ? OPTION_FLAG_LINKS : 0);
+ }
+ }
+ else
+ {
+ $options = $row[$feed->get('options')];
+ }
+
+ $title = ($row[$feed->get('title')]) ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : '');
+ $title = censor_text($title);
+
+ $item_row = array(
+ 'author' => ($feed->get('creator') !== NULL) ? $row[$feed->get('creator')] : '',
+ 'pubdate' => $user->format_date($row[$feed->get('date')], $feed_date_format, true),
+ 'link' => '',
+ 'title' => censor_text($title),
+ 'category' => ($config['feed_item_statistics']) ? $board_url . '/viewforum.' . $phpEx . '?f=' . $row['forum_id'] : '',
+ 'category_name' => ($config['feed_item_statistics']) ? utf8_htmlspecialchars($row['forum_name']) : '',
+ 'description' => censor_text(feed_generate_content($row[$feed->get('text')], $row[$feed->get('bbcode_uid')], $row[$feed->get('bitfield')], $options)),
+ 'statistics' => '',
+ );
+
+ // Adjust items, fill link, etc.
+ $feed->adjust_item($item_row, $row);
+
+ $item_vars[] = $item_row;
+}
+
+$feed->close();
+
+// Output page
+
+// gzip_compression
+if ($config['gzip_compress'])
+{
+ if (@extension_loaded('zlib') && !headers_sent())
+ {
+ ob_start('ob_gzhandler');
+ }
+}
+
+// IF debug extra is enabled and admin want to "explain" the page we need to set other headers...
+if (!defined('DEBUG_EXTRA') || !request_var('explain', 0) || !$auth->acl_get('a_'))
+{
+ header("Content-Type: application/atom+xml; charset=UTF-8");
+ header("Last-Modified: " . gmdate('D, d M Y H:i:s', time()) . ' GMT');
+}
+else
+{
+ header('Content-type: text/html; charset=UTF-8');
+ header('Cache-Control: private, no-cache="set-cookie"');
+ header('Expires: 0');
+ header('Pragma: no-cache');
+
+ $mtime = explode(' ', microtime());
+ $totaltime = $mtime[0] + $mtime[1] - $starttime;
+
+ if (method_exists($db, 'sql_report'))
+ {
+ $db->sql_report('display');
+ }
+
+ garbage_collection();
+ exit_handler();
+}
+
+echo '' . "\n";
+echo '
' . "\n";
+echo '' . "\n\n";
+
+echo (!empty($global_vars['FEED_TITLE'])) ? '' . $global_vars['FEED_TITLE'] . '' . "\n" : '';
+echo (!empty($global_vars['FEED_SUBTITLE'])) ? '' . $global_vars['FEED_SUBTITLE'] . '' . "\n" : '';
+echo (!empty($global_vars['FEED_LINK'])) ? '' . "\n" : '';
+echo '' . $global_vars['FEED_UPDATED'] . '' . "\n\n";
+
+echo '' . "\n";
+echo '' . $global_vars['SELF_LINK'] . '' . "\n";
+
+foreach ($item_vars as $row)
+{
+ echo '' . "\n";
+
+ if (!empty($row['author']))
+ {
+ echo '' . "\n";
+ }
+
+ echo '' . $row['pubdate'] . '' . "\n";
+ echo '' . $row['link'] . '' . "\n";
+ echo '' . "\n";
+ echo '' . "\n\n";
+
+ if (!empty($row['category']))
+ {
+ echo '' . "\n";
+ }
+
+ echo '' . $user->lang['STATISTICS'] . ': ' . $row['statistics'] . '';
+ }
+
+ echo '
' . "\n" . ']]>' . "\n";
+ echo '' . "\n";
+}
+
+echo '';
+
+garbage_collection();
+exit_handler();
+
+/**
+* Run links through append_sid(), prepend generate_board_url() and remove session id
+**/
+function feed_append_sid($url, $params)
+{
+ global $board_url;
+
+ $link = append_sid($board_url . $url, $params);
+
+ // Remove added sid - not as easy as it sounds. ;)
+ $link = (strpos($link, 'sid=') !== false) ? trim(preg_replace('/(&|&|\?)sid=[a-z0-9]+(&|&)?/', '\1', $link), '?& ') : $link;
+
+ // Now the only thing remaining could be an empty &
+ $link = (substr($link, -5) === '&') ? substr($link, 0, -5) : $link;
+ // And &#xxx
+ $link = str_replace('&#', '#', $link);
+
+ return $link;
+}
+
+/**
+* Generate text content
+**/
+function feed_generate_content($content, $uid, $bitfield, $options)
+{
+ global $user, $config, $phpbb_root_path, $phpEx, $board_url;
+
+ if (empty($content))
+ {
+ return '';
+ }
+
+ // Prepare some bbcodes for better parsing
+ $content = preg_replace("#\[quote(=".*?")?:$uid\]\s*(.*?)\s*\[/quote:$uid\]#si", "[quote$1:$uid]
$2
[/quote:$uid]", $content);
+
+ $content = generate_text_for_display($content, $uid, $bitfield, $options);
+
+ // Add newlines
+ $content = str_replace('
', '
' . "\n", $content);
+
+ // Relative Path to Absolute path, Windows style
+ $content = str_replace('./', $board_url . '/', $content);
+
+ // Remove "Select all" link and mouse events
+ $content = str_replace('
' .$user->lang['SELECT_ALL_CODE'] . '', '', $content);
+ $content = preg_replace('#(onkeypress|onclick)="(.*?)"#si', '', $content);
+
+ // Firefox does not support CSS for feeds, though
+
+ // Remove font sizes
+// $content = preg_replace('#
([^>]+)#iU', '\1', $content);
+
+ // Make text strong :P
+// $content = preg_replace('#
(.*?)#iU', '
\1', $content);
+
+ // Italic
+// $content = preg_replace('#
([^<]+)#iU', '
\1', $content);
+
+ // Underline
+// $content = preg_replace('#
([^<]+)#iU', '
\1', $content);
+
+ // Remove embed Windows Media Streams
+ $content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--#si', '', $content);
+
+ // Do not use < and >, because we want to retain code contained in [code][/code]
+
+ // Remove embed and objects
+ $content = preg_replace( '#<(object|embed)(.*?) (value|src)=(.*?) ([^[]+)(object|embed)>#si','
$1 ',$content);
+
+ // Remove some specials html tag, because somewhere there are a mod to allow html tags ;)
+ $content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', '
$1 ', $content);
+
+ // Remove Comments from inline attachments [ia]
+ $content = preg_replace('#
(.*?)(.*?)(.*?)
#si','$4',$content);
+
+ // Replace some entities with their unicode counterpart
+ $entities = array(
+ ' ' => "\xC2\xA0",
+ '•' => "\xE2\x80\xA2",
+ '·' => "\xC2\xB7",
+ '©' => "\xC2\xA9",
+ );
+
+ $content = str_replace(array_keys($entities), array_values($entities), $content);
+
+ // Remove CDATA blocks. ;)
+ $content = preg_replace('#\<\!\[CDATA\[(.*?)\]\]\>#s', '', $content);
+
+ // Other control characters
+ // $content = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $content);
+
+ return $content;
+}
+
+/**
+* Factory class to return correct object
+* @package phpBB3
+*/
+class phpbb_feed_factory
+{
+ /**
+ * Return correct object for specified mode
+ *
+ * @param string $mode The feeds mode.
+ * @param int $forum_id Forum id specified by the script if forum feed provided.
+ * @param int $topic_id Topic id specified by the script if topic feed provided.
+ *
+ * @return object Returns correct feeds object for specified mode.
+ */
+ function init($mode, $forum_id, $topic_id)
+ {
+ global $config;
+
+ switch ($mode)
+ {
+ case 'forums':
+ if (!$config['feed_overall_forums'])
+ {
+ return false;
+ }
+
+ return new phpbb_feed_forums();
+ break;
+
+ case 'topics':
+ if (!$config['feed_overall_topics'])
+ {
+ return false;
+ }
+
+ return new phpbb_feed_topics();
+ break;
+
+ case 'news':
+ global $db;
+
+ // Get at least one news forum
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $db->sql_query_limit($sql, 1, 0, 600);
+ $s_feed_news = (int) $db->sql_fetchfield('forum_id');
+ $db->sql_freeresult($result);
+
+ if (!$s_feed_news)
+ {
+ return false;
+ }
+
+ return new phpbb_feed_news();
+ break;
+
+ default:
+ // Forum and/or topic specified?
+ if ($topic_id && !$config['feed_topic'])
+ {
+ return false;
+ }
+
+ if ($forum_id && !$topic_id && !$config['feed_forum'])
+ {
+ return false;
+ }
+
+ return new phpbb_feed($forum_id, $topic_id);
+ break;
+ }
+ }
+}
+
+/**
+* Base/default Feed class if no mode is specified.
+* This can be the overall site feed or a forum/topic feed.
+* @package phpBB3
+*/
+class phpbb_feed
+{
+ /**
+ * Forum id specified for forum feed.
+ */
+ var $forum_id = 0;
+
+ /**
+ * Topic id specified for topic feed.
+ */
+ var $topic_id = 0;
+
+ /**
+ * SQL Query to be executed to get feed items
+ */
+ var $sql;
+
+ /**
+ * Keys specified for retrieval of title, content, etc.
+ */
+ var $keys = array();
+
+ /**
+ * An array of excluded forum ids.
+ */
+ var $excluded_forums_ary = NULL;
+
+ /**
+ * Number of items to fetch
+ */
+ var $num_items;
+
+ /**
+ * boolean to determine if items array is filled or not
+ */
+ var $items_filled = false;
+
+ /**
+ * array holding items
+ */
+ var $items = array();
+
+ /**
+ * Default setting for last x days
+ */
+ var $sort_days = 30;
+
+ /**
+ * Default cache time of entries in seconds
+ */
+ var $cache_time = 300;
+
+ /**
+ * Separator for title elements to separate items (for example forum / topic)
+ */
+ var $separator = "\xE2\x80\xA2"; // •
+
+ /**
+ * Constructor. Set standard keys.
+ */
+ function phpbb_feed($forum_id = 0, $topic_id = 0)
+ {
+ global $config;
+
+ $this->forum_id = $forum_id;
+ $this->topic_id = $topic_id;
+
+ $this->sql = array();
+
+ // Set some values for pagination
+ $this->num_items = $config['feed_limit'];
+ $this->set_keys();
+ }
+
+ function set_keys()
+ {
+ // Set keys for items...
+ $this->set('title', 'post_subject');
+ $this->set('title2', 'topic_title');
+ $this->set('author_id', 'user_id');
+ $this->set('creator', 'username');
+ $this->set('text', 'post_text');
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+ $this->set('date', 'post_time');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+ }
+
+ function open()
+ {
+ if (!$this->forum_id && !$this->topic_id)
+ {
+ return;
+ }
+ else if ($this->forum_id && !$this->topic_id)
+ {
+ global $db, $user, $global_vars;
+
+ $sql = 'SELECT forum_name
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $this->forum_id;
+ $result = $db->sql_query($sql);
+
+ $global_vars['FEED_MODE'] = $user->lang['FORUM'] . ': ' . $db->sql_fetchfield('forum_name');
+
+ $db->sql_freeresult($result);
+ }
+ else if ($this->topic_id)
+ {
+ global $db, $user, $global_vars;
+
+ $sql = 'SELECT topic_title
+ FROM ' . TOPICS_TABLE . '
+ WHERE topic_id = ' . $this->topic_id;
+ $result = $db->sql_query($sql);
+
+ $global_vars['FEED_MODE'] = $user->lang['TOPIC'] . ': ' . $db->sql_fetchfield('topic_title');
+
+ $db->sql_freeresult($result);
+ }
+ }
+
+ function close()
+ {
+ if (!empty($this->result))
+ {
+ global $db;
+
+ $db->sql_freeresult($this->result);
+ }
+ }
+
+ /**
+ * Set key
+ */
+ function set($key, $value)
+ {
+ $this->keys[$key] = $value;
+ }
+
+ /**
+ * Get key
+ */
+ function get($key)
+ {
+ return (isset($this->keys[$key])) ? $this->keys[$key] : NULL;
+ }
+
+ /**
+ * Return array of excluded forums
+ */
+ function excluded_forums()
+ {
+ if ($this->excluded_forums_ary !== NULL)
+ {
+ return $this->excluded_forums_ary;
+ }
+
+ global $auth, $db, $config, $phpbb_root_path, $phpEx, $user;
+
+ // Which forums should not be searched ?
+ $exclude_forums = array();
+
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '<> 0');
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $exclude_forums[] = (int) $row['forum_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // Exclude forums the user is not able to read
+ $this->excluded_forums_ary = array_keys($auth->acl_getf('!f_read', true));
+ $this->excluded_forums_ary = (sizeof($exclude_forums)) ? array_merge($exclude_forums, $this->excluded_forums_ary) : $this->excluded_forums_ary;
+
+ $not_in_fid = (sizeof($this->excluded_forums_ary)) ? 'WHERE (' . $db->sql_in_set('f.forum_id', $this->excluded_forums_ary, true) . ' AND ' . $db->sql_in_set('f.parent_id', $this->excluded_forums_ary, true) . ") OR (f.forum_password <> '' AND fa.user_id <> " . (int) $user->data['user_id'] . ')' : '';
+
+ $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.right_id, f.forum_password, fa.user_id
+ FROM ' . FORUMS_TABLE . ' f
+ LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id
+ AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
+ $not_in_fid
+ ORDER BY f.left_id";
+ $result = $db->sql_query($sql);
+
+ $right_id = 0;
+ while ($row = $db->sql_fetchrow($result))
+ {
+ // Exclude passworded forum completely
+ if ($row['forum_password'] && $row['user_id'] != $user->data['user_id'])
+ {
+ $this->excluded_forums_ary[] = (int) $row['forum_id'];
+ continue;
+ }
+
+ if ($row['right_id'] > $right_id)
+ {
+ $right_id = (int) $row['right_id'];
+ }
+ else if ($row['right_id'] < $right_id)
+ {
+ continue;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $this->excluded_forums_ary;
+ }
+
+ /**
+ * Get SQL query for fetching items
+ */
+ function get_sql()
+ {
+ global $db;
+
+ $post_ids = array();
+
+ // Search for topics in last X days
+ $last_post_time_sql = ($this->sort_days) ? ' AND t.topic_last_post_time > ' . (time() - ($this->sort_days * 24 * 3600)) : '';
+
+ // Fetch latest post, grouped by topic...
+ if (!$this->forum_id && !$this->topic_id)
+ {
+ // First of all, the post ids...
+ $not_in_fid = (sizeof($this->excluded_forums())) ? ' AND ' . $db->sql_in_set('t.forum_id', $this->excluded_forums(), true) : '';
+
+ $sql = 'SELECT t.topic_last_post_id
+ FROM ' . TOPICS_TABLE . ' t
+ WHERE t.topic_approved = 1
+ AND t.topic_moved_id = 0' .
+ $not_in_fid .
+ $last_post_time_sql . '
+ ORDER BY t.topic_last_post_time DESC';
+ $result = $db->sql_query_limit($sql, $this->num_items);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_last_post_id'];
+ }
+ $db->sql_freeresult($result);
+ }
+ // Fetch latest posts from forum
+ else if (!$this->topic_id && $this->forum_id)
+ {
+ // Make sure the forum is not listed within the forbidden ones. ;)
+ if (in_array($this->forum_id, $this->excluded_forums()))
+ {
+ return false;
+ }
+
+ // Determine which forums to fetch
+ $not_in_fid = (sizeof($this->excluded_forums())) ? ' AND ' . $db->sql_in_set('f1.forum_id', $this->excluded_forums(), true) : '';
+
+ // Determine forum childs...
+ $sql = 'SELECT f2.forum_id
+ FROM ' . FORUMS_TABLE . ' f1, ' . FORUMS_TABLE . ' f2
+ WHERE f1.forum_id = ' . $this->forum_id . '
+ AND (f2.left_id BETWEEN f1.left_id AND f1.right_id' . $not_in_fid . ')';
+ $result = $db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $forum_ids[] = (int) $row['forum_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // Now select from forums...
+ $sql = 'SELECT t.topic_last_post_id
+ FROM ' . TOPICS_TABLE . ' t
+ WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . '
+ AND t.topic_approved = 1
+ AND t.topic_moved_id = 0' .
+ $last_post_time_sql . '
+ ORDER BY t.topic_last_post_time DESC';
+ $result = $db->sql_query_limit($sql, $this->num_items);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_last_post_id'];
+ }
+ $db->sql_freeresult($result);
+ }
+ // Fetch last posts from specified topic...
+ else if ($this->topic_id)
+ {
+ // First of all, determine the forum...
+ $sql = 'SELECT forum_id
+ FROM ' . TOPICS_TABLE . '
+ WHERE topic_id = ' . $this->topic_id;
+ $result = $db->sql_query_limit($sql, 1);
+ $this->forum_id = (int) $db->sql_fetchfield('forum_id');
+ $db->sql_freeresult($result);
+
+ // non-global announcement
+ if ($this->forum_id && in_array($this->forum_id, $this->excluded_forums()))
+ {
+ return false;
+ }
+
+ $sql = 'SELECT post_id
+ FROM ' . POSTS_TABLE . '
+ WHERE topic_id = ' . $this->topic_id . '
+ AND post_approved = 1
+ ORDER BY post_time DESC';
+ $result = $db->sql_query_limit($sql, $this->num_items);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['post_id'];
+ }
+ $db->sql_freeresult($result);
+ }
+
+ if (!sizeof($post_ids))
+ {
+ return false;
+ }
+
+ // Now build sql query for obtaining items
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name, f.forum_desc_options, ' .
+ 't.topic_last_post_time, t.topic_id, t.topic_title, t.topic_time, t.topic_replies, t.topic_views, ' .
+ 'p.post_id, p.post_time, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id, u.user_email, u.user_colour',
+ 'FROM' => array(
+ POSTS_TABLE => 'p',
+ TOPICS_TABLE => 't',
+ FORUMS_TABLE => 'f',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => $db->sql_in_set('p.post_id', $post_ids) . '
+ AND f.forum_id = p.forum_id
+ AND t.topic_id = p.topic_id
+ AND u.user_id = p.poster_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function get_item()
+ {
+ global $db, $cache;
+
+ // Disable cache if it is not a guest or a bot but a registered user
+ if ($this->cache_time)
+ {
+ global $user;
+
+ // We check this here because we call get_item() quite often
+ if (!empty($user) && $user->data['is_registered'])
+ {
+ $this->cache_time = 0;
+ }
+ }
+
+ if (!$this->cache_time)
+ {
+ if (empty($this->result))
+ {
+ if (!$this->get_sql())
+ {
+ return false;
+ }
+
+ // Query database
+ $sql = $db->sql_build_query('SELECT', $this->sql);
+ $this->result = $db->sql_query_limit($sql, $this->num_items);
+ }
+
+ return $db->sql_fetchrow($this->result);
+ }
+ else
+ {
+ if (empty($this->items_filled))
+ {
+ // Try to load result set...
+ $cache_filename = substr(get_class($this), strlen('phpbb_'));
+
+ if (($this->items = $cache->get('_' . $cache_filename)) === false)
+ {
+ $this->items = array();
+
+ if ($this->get_sql())
+ {
+ // Query database
+ $sql = $db->sql_build_query('SELECT', $this->sql);
+ $result = $db->sql_query_limit($sql, $this->num_items);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $this->items[] = $row;
+ }
+ $db->sql_freeresult($result);
+ }
+
+ $cache->put('_' . $cache_filename, $this->items, $this->cache_time);
+ }
+
+ $this->items_filled = true;
+ }
+
+ $row = array_shift($this->items);
+ return (!$row) ? false : $row;
+ }
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ global $phpEx, $config;
+
+ $item_row['title'] = (!$this->topic_id) ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ $item_row['link'] = feed_append_sid('/viewtopic.' . $phpEx, "t={$row['topic_id']}&p={$row['post_id']}#p{$row['post_id']}");
+
+ if ($config['feed_item_statistics'])
+ {
+ global $user;
+
+ $user_link = '
' . $row['username'] . '';
+
+ $time = ($this->topic_id) ? $row['post_time'] : $row['topic_time'];
+
+ $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $user_link . ' - ' . $user->format_date($time). ' - ' . $user->lang['REPLIES'] . ' ' . $row['topic_replies'] . ' - ' . $user->lang['VIEWS'] . ' ' . $row['topic_views'];
+ }
+ }
+}
+
+class phpbb_feed_forums extends phpbb_feed
+{
+ function set_keys()
+ {
+ global $config;
+
+ $this->set('title', 'forum_name');
+ $this->set('text', 'forum_desc');
+ $this->set('bitfield', 'forum_desc_bitfield');
+ $this->set('bbcode_uid','forum_desc_uid');
+ $this->set('date', 'forum_last_post_time');
+ $this->set('options', 'forum_desc_options');
+
+ $this->num_items = $config['feed_overall_forums_limit'];
+ }
+
+ function open()
+ {
+ global $user, $global_vars;
+
+ $global_vars['FEED_MODE'] = $user->lang['FORUMS'];
+ }
+
+ function get_sql()
+ {
+ global $db;
+
+ $not_in_fid = (sizeof($this->excluded_forums())) ? ' AND ' . $db->sql_in_set('f.forum_id', $this->excluded_forums(), true) : '';
+
+ // Build SQL Query
+ $this->sql = array(
+ 'SELECT' => 'f.*',
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'WHERE' => 'f.forum_type = ' . FORUM_POST . '
+ AND (f.forum_last_post_id > 0' . $not_in_fid . ')',
+ 'ORDER_BY' => 'f.left_id',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ global $phpEx, $config;
+
+ $item_row['link'] = feed_append_sid('/viewforum.' . $phpEx, 'f=' . $row['forum_id']);
+
+ if ($config['feed_item_statistics'])
+ {
+ global $user;
+
+ $item_row['statistics'] = sprintf($user->lang['TOTAL_TOPICS_OTHER'], $row['forum_topics']) . ' - ' . sprintf($user->lang['TOTAL_POSTS_OTHER'], $row['forum_posts']);
+ }
+ }
+}
+
+class phpbb_feed_news extends phpbb_feed
+{
+ function set_keys()
+ {
+ global $config;
+
+ $this->set('title', 'topic_title');
+ $this->set('title2', 'forum_name');
+ $this->set('author_id', 'topic_poster');
+ $this->set('creator', 'topic_first_poster_name');
+ $this->set('text', 'post_text');
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+ $this->set('date', 'topic_time');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+
+ $this->num_items = (int) $config['feed_overall_forums_limit'];
+ }
+
+ function open()
+ {
+ global $user, $global_vars;
+
+ $global_vars['FEED_MODE'] = $user->lang['FEED_NEWS'];
+ }
+
+ function get_sql()
+ {
+ global $db, $config;
+
+ // Get news forums...
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $db->sql_query($sql);
+
+ $in_fid_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $in_fid_ary[] = (int) $row['forum_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (!sizeof($in_fid_ary))
+ {
+ return false;
+ }
+
+ // Build SQL Query
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_password, f.forum_name, f.forum_topics, f.forum_posts, f.parent_id, f.left_id, f.right_id,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_views, t.topic_time,
+ p.post_id, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url,
+ u.username, u.user_id, u.user_email, u.user_colour',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ FORUMS_TABLE => 'f',
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => $db->sql_in_set('t.forum_id', $in_fid_ary) . '
+ AND f.forum_id = t.forum_id
+ AND p.post_id = t.topic_first_post_id
+ AND t.topic_poster = u.user_id
+ AND t.topic_moved_id = 0',
+ 'ORDER_BY' => 't.topic_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ global $phpEx, $config;
+
+ $item_row['link'] = feed_append_sid('/viewtopic.' . $phpEx, 't=' . $row['topic_id'] . '&p=' . $row['post_id'] . '#p' . $row['post_id']);
+
+ if ($config['feed_item_statistics'])
+ {
+ global $user;
+
+ $user_link = '
' . $row[$this->get('creator')] . '';
+
+ $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $user_link . ' - ' . $user->format_date($row['topic_time']). ' - ' . $user->lang['REPLIES'] . ' ' . $row['topic_replies'] . ' - ' . $user->lang['VIEWS'] . ' ' . $row['topic_views'];
+ }
+ }
+}
+
+class phpbb_feed_topics extends phpbb_feed
+{
+ function set_keys()
+ {
+ global $config;
+
+ $this->set('title', 'topic_title');
+ $this->set('title2', 'forum_name');
+ $this->set('author_id', 'topic_poster');
+ $this->set('creator', 'topic_first_poster_name');
+ $this->set('text', 'post_text');
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+ $this->set('date', 'topic_time');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+
+ $this->num_items = (int) $config['feed_overall_topics_limit'];
+ }
+
+ function open()
+ {
+ global $user, $global_vars;
+
+ $global_vars['FEED_MODE'] = $user->lang['TOPICS'];
+ }
+
+ function get_sql()
+ {
+ global $db, $config;
+
+ $post_ids = array();
+ $not_in_fid = (sizeof($this->excluded_forums())) ? ' AND ' . $db->sql_in_set('t.forum_id', $this->excluded_forums(), true) : '';
+
+ // Search for topics in last x days
+ $last_post_time_sql = ($this->sort_days) ? ' AND t.topic_last_post_time > ' . (time() - ($this->sort_days * 24 * 3600)) : '';
+
+ // Last x topics from all forums, with first post from topic...
+ $sql = 'SELECT t.topic_first_post_id
+ FROM ' . TOPICS_TABLE . ' t
+ WHERE t.topic_approved = 1
+ AND t.topic_moved_id = 0' .
+ $not_in_fid .
+ $last_post_time_sql . '
+ ORDER BY t.topic_last_post_time DESC';
+ $result = $db->sql_query_limit($sql, $this->num_items);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_first_post_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (!sizeof($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_password, f.forum_name, f.forum_topics, f.forum_posts, f.parent_id, f.left_id, f.right_id,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_views, t.topic_time,
+ p.post_id, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url,
+ u.username, u.user_id, u.user_email, u.user_colour',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ FORUMS_TABLE => 'f',
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => $db->sql_in_set('p.post_id', $post_ids) . '
+ AND f.forum_id = p.forum_id
+ AND t.topic_id = p.topic_id
+ AND u.user_id = p.poster_id',
+ 'ORDER_BY' => 't.topic_last_post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ global $phpEx, $config;
+
+ $item_row['link'] = feed_append_sid('/viewtopic.' . $phpEx, 't=' . $row['topic_id'] . '&p=' . $row['post_id'] . '#p' . $row['post_id']);
+
+ if ($config['feed_item_statistics'])
+ {
+ global $user;
+
+ $user_link = '
' . $row[$this->get('creator')] . '';
+
+ $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $user_link . ' - ' . $user->format_date($row['topic_time']). ' - ' . $user->lang['REPLIES'] . ' ' . $row['topic_replies'] . ' - ' . $user->lang['VIEWS'] . ' ' . $row['topic_views'];
+ }
+ }
+}
+
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_apc.php b/phpBB/includes/acm/acm_apc.php
new file mode 100644
index 0000000000..1a487f94ad
--- /dev/null
+++ b/phpBB/includes/acm/acm_apc.php
@@ -0,0 +1,84 @@
+key_prefix . $var);
+ }
+
+ /**
+ * Store data in the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @param mixed $data Data to store
+ * @param int $ttl Time-to-live of cached data
+ * @return bool True if the operation succeeded
+ */
+ function _write($var, $data, $ttl = 2592000)
+ {
+ return apc_store($this->key_prefix . $var, $data, $ttl);
+ }
+
+ /**
+ * Remove an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if the operation succeeded
+ */
+ function _delete($var)
+ {
+ return apc_delete($this->key_prefix . $var);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_eaccelerator.php b/phpBB/includes/acm/acm_eaccelerator.php
new file mode 100644
index 0000000000..1a3cf3c0f7
--- /dev/null
+++ b/phpBB/includes/acm/acm_eaccelerator.php
@@ -0,0 +1,120 @@
+key_prefix
+ eaccelerator_rm(substr($var['name'], 1));
+ }
+
+ parent::purge();
+ }
+
+ /**
+ * Perform cache garbage collection
+ *
+ * @return void
+ */
+ function tidy()
+ {
+ eaccelerator_gc();
+
+ set_config('cache_last_gc', time(), true);
+ }
+
+ /**
+ * Fetch an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return mixed Cached data
+ */
+ function _read($var)
+ {
+ $result = eaccelerator_get($this->key_prefix . $var);
+
+ if ($result === null)
+ {
+ return false;
+ }
+
+ // Handle serialized objects
+ if (is_string($result) && strpos($result, $this->serialize_header . 'O:') === 0)
+ {
+ $result = unserialize(substr($result, strlen($this->serialize_header)));
+ }
+
+ return $result;
+ }
+
+ /**
+ * Store data in the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @param mixed $data Data to store
+ * @param int $ttl Time-to-live of cached data
+ * @return bool True if the operation succeeded
+ */
+ function _write($var, $data, $ttl = 2592000)
+ {
+ // Serialize objects and make them easy to detect
+ $data = (is_object($data)) ? $this->serialize_header . serialize($data) : $data;
+
+ return eaccelerator_put($this->key_prefix . $var, $data, $ttl);
+ }
+
+ /**
+ * Remove an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if the operation succeeded
+ */
+ function _delete($var)
+ {
+ return eaccelerator_rm($this->key_prefix . $var);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php
index f9ff92e19d..234be5c5d1 100644
--- a/phpBB/includes/acm/acm_file.php
+++ b/phpBB/includes/acm/acm_file.php
@@ -3,7 +3,7 @@
*
* @package acm
* @version $Id$
-* @copyright (c) 2005 phpBB Group
+* @copyright (c) 2005, 2009 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
@@ -44,17 +44,7 @@ class acm
*/
function load()
{
- global $phpEx;
- if (file_exists($this->cache_dir . 'data_global.' . $phpEx))
- {
- @include($this->cache_dir . 'data_global.' . $phpEx);
- }
- else
- {
- return false;
- }
-
- return true;
+ return $this->_read('data_global');
}
/**
@@ -86,22 +76,7 @@ class acm
global $phpEx;
- if ($fp = @fopen($this->cache_dir . 'data_global.' . $phpEx, 'wb'))
- {
- @flock($fp, LOCK_EX);
- fwrite($fp, "vars = " . var_export($this->vars, true) . ";\n\n\$this->var_expires = " . var_export($this->var_expires, true) . "\n?>");
- @flock($fp, LOCK_UN);
- fclose($fp);
-
- if (!function_exists('phpbb_chmod'))
- {
- global $phpbb_root_path;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
- }
-
- phpbb_chmod($this->cache_dir . 'data_global.' . $phpEx, CHMOD_READ | CHMOD_WRITE);
- }
- else
+ if (!$this->_write('data_global'))
{
// Now, this occurred how often? ... phew, just tell the user then...
if (!@is_writable($this->cache_dir))
@@ -132,6 +107,8 @@ class acm
return;
}
+ $time = time();
+
while (($entry = readdir($dir)) !== false)
{
if (!preg_match('/^(sql_|data_(?!global))/', $entry))
@@ -139,9 +116,20 @@ class acm
continue;
}
- $expired = true;
- @include($this->cache_dir . $entry);
- if ($expired)
+ if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
+ {
+ continue;
+ }
+
+ // Skip the PHP header
+ fgets($handle);
+
+ // Skip expiration
+ $expires = (int) fgets($handle);
+
+ fclose($handle);
+
+ if ($time >= $expires)
{
$this->remove_file($this->cache_dir . $entry);
}
@@ -157,7 +145,7 @@ class acm
foreach ($this->var_expires as $var_name => $expires)
{
- if (time() > $expires)
+ if ($time >= $expires)
{
$this->destroy($var_name);
}
@@ -181,8 +169,7 @@ class acm
return false;
}
- @include($this->cache_dir . "data{$var_name}.$phpEx");
- return (isset($data)) ? $data : false;
+ return $this->_read('data' . $var_name);
}
else
{
@@ -197,23 +184,7 @@ class acm
{
if ($var_name[0] == '_')
{
- global $phpEx;
-
- if ($fp = @fopen($this->cache_dir . "data{$var_name}.$phpEx", 'wb'))
- {
- @flock($fp, LOCK_EX);
- fwrite($fp, " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$data = " . (sizeof($var) ? "unserialize(" . var_export(serialize($var), true) . ");" : 'array();') . "\n\n?>");
- @flock($fp, LOCK_UN);
- fclose($fp);
-
- if (!function_exists('phpbb_chmod'))
- {
- global $phpbb_root_path;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
- }
-
- phpbb_chmod($this->cache_dir . "data{$var_name}.$phpEx", CHMOD_READ | CHMOD_WRITE);
- }
+ $this->_write('data' . $var_name, $var, time() + $ttl);
}
else
{
@@ -288,32 +259,31 @@ class acm
continue;
}
- // The following method is more failproof than simply assuming the query is on line 3 (which it should be)
- $check_line = @file_get_contents($this->cache_dir . $entry);
-
- if (empty($check_line))
+ if (!($handle = @fopen($this->cache_dir . $entry, 'rb')))
{
continue;
}
- // Now get the contents between /* and */
- $check_line = substr($check_line, strpos($check_line, '/* ') + 3, strpos($check_line, ' */') - strpos($check_line, '/* ') - 3);
+ // Skip the PHP header
+ fgets($handle);
+
+ // Skip expiration
+ fgets($handle);
+
+ // Grab the query, remove the LF
+ $query = substr(fgets($handle), 0, -1);
+
+ fclose($handle);
- $found = false;
foreach ($table as $check_table)
{
// Better catch partial table names than no table names. ;)
- if (strpos($check_line, $check_table) !== false)
+ if (strpos($query, $check_table) !== false)
{
- $found = true;
+ $this->remove_file($this->cache_dir . $entry);
break;
}
}
-
- if ($found)
- {
- $this->remove_file($this->cache_dir . $entry);
- }
}
closedir($dir);
@@ -371,29 +341,16 @@ class acm
*/
function sql_load($query)
{
- global $phpEx;
-
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
+
+ if (($rowset = $this->_read('sql_' . md5($query))) === false)
+ {
+ return false;
+ }
+
$query_id = sizeof($this->sql_rowset);
-
- if (!file_exists($this->cache_dir . 'sql_' . md5($query) . ".$phpEx"))
- {
- return false;
- }
-
- @include($this->cache_dir . 'sql_' . md5($query) . ".$phpEx");
-
- if (!isset($expired))
- {
- return false;
- }
- else if ($expired)
- {
- $this->remove_file($this->cache_dir . 'sql_' . md5($query) . ".$phpEx", true);
- return false;
- }
-
+ $this->sql_rowset[$query_id] = $rowset;
$this->sql_row_pointer[$query_id] = 0;
return $query_id;
@@ -404,41 +361,23 @@ class acm
*/
function sql_save($query, &$query_result, $ttl)
{
- global $db, $phpEx;
+ global $db;
// Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
- $filename = $this->cache_dir . 'sql_' . md5($query) . '.' . $phpEx;
- if ($fp = @fopen($filename, 'wb'))
+ $query_id = sizeof($this->sql_rowset);
+ $this->sql_rowset[$query_id] = array();
+ $this->sql_row_pointer[$query_id] = 0;
+
+ while ($row = $db->sql_fetchrow($query_result))
{
- @flock($fp, LOCK_EX);
-
- $query_id = sizeof($this->sql_rowset);
- $this->sql_rowset[$query_id] = array();
- $this->sql_row_pointer[$query_id] = 0;
-
- while ($row = $db->sql_fetchrow($query_result))
- {
- $this->sql_rowset[$query_id][] = $row;
- }
- $db->sql_freeresult($query_result);
-
- $file = " " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n";
-
- fwrite($fp, $file . "\n\$this->sql_rowset[\$query_id] = " . (sizeof($this->sql_rowset[$query_id]) ? "unserialize(" . var_export(serialize($this->sql_rowset[$query_id]), true) . ");" : 'array();') . "\n\n?>");
- @flock($fp, LOCK_UN);
- fclose($fp);
-
- if (!function_exists('phpbb_chmod'))
- {
- global $phpbb_root_path;
- include($phpbb_root_path . 'includes/functions.' . $phpEx);
- }
-
- phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE);
+ $this->sql_rowset[$query_id][] = $row;
+ }
+ $db->sql_freeresult($query_result);
+ if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query))
+ {
$query_result = $query_id;
}
}
@@ -507,6 +446,262 @@ class acm
return true;
}
+ /**
+ * Read cached data from a specified file
+ *
+ * @access private
+ * @param string $filename Filename to write
+ * @return mixed False if an error was encountered, otherwise the data type of the cached data
+ */
+ function _read($filename)
+ {
+ global $phpEx;
+
+ $file = "{$this->cache_dir}$filename.$phpEx";
+
+ $type = substr($filename, 0, strpos($filename, '_'));
+
+ if (!file_exists($file))
+ {
+ return false;
+ }
+
+ if (!($handle = @fopen($file, 'rb')))
+ {
+ return false;
+ }
+
+ // Skip the PHP header
+ fgets($handle);
+
+ if ($filename == 'data_global')
+ {
+ $this->vars = $this->var_expires = array();
+
+ $time = time();
+
+ while (($expires = (int) fgets($handle)) && !feof($handle))
+ {
+ // Number of bytes of data
+ $bytes = substr(fgets($handle), 0, -1);
+
+ if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0)
+ {
+ // We cannot process the file without a valid number of bytes
+ // so we discard it
+ fclose($handle);
+
+ $this->vars = $this->var_expires = array();
+ $this->is_modified = false;
+
+ $this->remove_file($file);
+
+ return false;
+ }
+
+ if ($time >= $expires)
+ {
+ fseek($handle, $bytes, SEEK_CUR);
+
+ continue;
+ }
+
+ $var_name = substr(fgets($handle), 0, -1);
+
+ // Read the length of bytes that consists of data.
+ $data = fread($handle, $bytes - strlen($var_name));
+ $data = @unserialize($data);
+
+ // Don't use the data if it was invalid
+ if ($data !== false)
+ {
+ $this->vars[$var_name] = $data;
+ $this->var_expires[$var_name] = $expires;
+ }
+
+ // Absorb the LF
+ fgets($handle);
+ }
+
+ fclose($handle);
+
+ $this->is_modified = false;
+
+ return true;
+ }
+ else
+ {
+ $data = false;
+ $line = 0;
+
+ while (($buffer = fgets($handle)) && !feof($handle))
+ {
+ $buffer = substr($buffer, 0, -1); // Remove the LF
+
+ // $buffer is only used to read integers
+ // if it is non numeric we have an invalid
+ // cache file, which we will now remove.
+ if (!is_numeric($buffer))
+ {
+ break;
+ }
+
+ if ($line == 0)
+ {
+ $expires = (int) $buffer;
+
+ if (time() >= $expires)
+ {
+ break;
+ }
+
+ if ($type == 'sql')
+ {
+ // Skip the query
+ fgets($handle);
+ }
+ }
+ else if ($line == 1)
+ {
+ $bytes = (int) $buffer;
+
+ // Never should have 0 bytes
+ if (!$bytes)
+ {
+ break;
+ }
+
+ // Grab the serialized data
+ $data = fread($handle, $bytes);
+
+ // Read 1 byte, to trigger EOF
+ fread($handle, 1);
+
+ if (!feof($handle))
+ {
+ // Somebody tampered with our data
+ $data = false;
+ }
+ break;
+ }
+ else
+ {
+ // Something went wrong
+ break;
+ }
+ $line++;
+ }
+ fclose($handle);
+
+ // unserialize if we got some data
+ $data = ($data !== false) ? @unserialize($data) : $data;
+
+ if ($data === false)
+ {
+ $this->remove_file($file);
+ return false;
+ }
+
+ return $data;
+ }
+ }
+
+ /**
+ * Write cache data to a specified file
+ *
+ * 'data_global' is a special case and the generated format is different for this file:
+ *
+ *
+ * (expiration)
+ * (length of var and serialised data)
+ * (var)
+ * (serialised data)
+ * ... (repeat)
+ *
+ *
+ * The other files have a similar format:
+ *
+ *
+ * (expiration)
+ * (query) [SQL files only]
+ * (length of serialised data)
+ * (serialised data)
+ *
+ *
+ * @access private
+ * @param string $filename Filename to write
+ * @param mixed $data Data to store
+ * @param int $expires Timestamp when the data expires
+ * @param string $query Query when caching SQL queries
+ * @return bool True if the file was successfully created, otherwise false
+ */
+ function _write($filename, $data = null, $expires = 0, $query = '')
+ {
+ global $phpEx;
+
+ $file = "{$this->cache_dir}$filename.$phpEx";
+
+ if ($handle = @fopen($file, 'wb'))
+ {
+ @flock($handle, LOCK_EX);
+
+ // File header
+ fwrite($handle, '<' . '?php exit; ?' . '>');
+
+ if ($filename == 'data_global')
+ {
+ // Global data is a different format
+ foreach ($this->vars as $var => $data)
+ {
+ if (strpos($var, "\r") !== false || strpos($var, "\n") !== false)
+ {
+ // CR/LF would cause fgets() to read the cache file incorrectly
+ // do not cache test entries, they probably won't be read back
+ // the cache keys should really be alphanumeric with a few symbols.
+ continue;
+ }
+ $data = serialize($data);
+
+ // Write out the expiration time
+ fwrite($handle, "\n" . $this->var_expires[$var] . "\n");
+
+ // Length of the remaining data for this var (ignoring two LF's)
+ fwrite($handle, strlen($data . $var) . "\n");
+ fwrite($handle, $var . "\n");
+ fwrite($handle, $data);
+ }
+ }
+ else
+ {
+ fwrite($handle, "\n" . $expires . "\n");
+
+ if (strpos($filename, 'sql_') === 0)
+ {
+ fwrite($handle, $query . "\n");
+ }
+ $data = serialize($data);
+
+ fwrite($handle, strlen($data) . "\n");
+ fwrite($handle, $data);
+ }
+
+ @flock($handle, LOCK_UN);
+ fclose($handle);
+
+ if (!function_exists('phpbb_chmod'))
+ {
+ global $phpbb_root_path;
+ include($phpbb_root_path . 'includes/functions.' . $phpEx);
+ }
+
+ phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE);
+
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Removes/unlinks file
*/
diff --git a/phpBB/includes/acm/acm_memcache.php b/phpBB/includes/acm/acm_memcache.php
new file mode 100644
index 0000000000..3077ee9615
--- /dev/null
+++ b/phpBB/includes/acm/acm_memcache.php
@@ -0,0 +1,124 @@
+memcache = new Memcache;
+ $this->memcache->connect(PHPBB_ACM_MEMCACHE_HOST, PHPBB_ACM_MEMCACHE_PORT);
+ $this->flags = (PHPBB_ACM_MEMCACHE_COMPRESS) ? MEMCACHE_COMPRESSED : 0;
+ }
+
+ /**
+ * Unload the cache resources
+ *
+ * @return void
+ */
+ function unload()
+ {
+ parent::unload();
+
+ $this->memcache->close();
+ }
+
+ /**
+ * Purge cache data
+ *
+ * @return void
+ */
+ function purge()
+ {
+ $this->memcache->flush();
+
+ parent::purge();
+ }
+
+ /**
+ * Fetch an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return mixed Cached data
+ */
+ function _read($var)
+ {
+ return $this->memcache->get($this->key_prefix . $var);
+ }
+
+ /**
+ * Store data in the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @param mixed $data Data to store
+ * @param int $ttl Time-to-live of cached data
+ * @return bool True if the operation succeeded
+ */
+ function _write($var, $data, $ttl = 2592000)
+ {
+ return $this->memcache->set($this->key_prefix . $var, $data, $this->flags, $ttl);
+ }
+
+ /**
+ * Remove an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if the operation succeeded
+ */
+ function _delete($var)
+ {
+ return $this->memcache->delete($this->key_prefix . $var);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_memory.php b/phpBB/includes/acm/acm_memory.php
new file mode 100644
index 0000000000..1ed4fb0d55
--- /dev/null
+++ b/phpBB/includes/acm/acm_memory.php
@@ -0,0 +1,426 @@
+cache_dir = $phpbb_root_path . 'cache/';
+ $this->key_prefix = substr(md5($dbname . $table_prefix), 0, 8) . '_';
+
+ if (!isset($this->extension) || !extension_loaded($this->extension))
+ {
+ global $acm_type;
+
+ trigger_error("Could not find required extension [{$this->extension}] for the ACM module $acm_type.", E_USER_ERROR);
+ }
+ }
+
+ /**
+ * Load global cache
+ */
+ function load()
+ {
+ // grab the global cache
+ $this->vars = $this->_read('global');
+
+ if ($this->vars !== false)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Unload cache object
+ */
+ function unload()
+ {
+ $this->save();
+ unset($this->vars);
+ unset($this->sql_rowset);
+ unset($this->sql_row_pointer);
+
+ $this->vars = array();
+ $this->sql_rowset = array();
+ $this->sql_row_pointer = array();
+ }
+
+ /**
+ * Save modified objects
+ */
+ function save()
+ {
+ if (!$this->is_modified)
+ {
+ return;
+ }
+
+ $this->_write('global', $this->vars, 2592000);
+
+ $this->is_modified = false;
+ }
+
+ /**
+ * Tidy cache
+ */
+ function tidy()
+ {
+ // cache has auto GC, no need to have any code here :)
+
+ set_config('cache_last_gc', time(), true);
+ }
+
+ /**
+ * Get saved cache object
+ */
+ function get($var_name)
+ {
+ if ($var_name[0] == '_')
+ {
+ if (!$this->_exists($var_name))
+ {
+ return false;
+ }
+
+ return $this->_read($var_name);
+ }
+ else
+ {
+ return ($this->_exists($var_name)) ? $this->vars[$var_name] : false;
+ }
+ }
+
+ /**
+ * Put data into cache
+ */
+ function put($var_name, $var, $ttl = 2592000)
+ {
+ if ($var_name[0] == '_')
+ {
+ $this->_write($var_name, $var, $ttl);
+ }
+ else
+ {
+ $this->vars[$var_name] = $var;
+ $this->is_modified = true;
+ }
+ }
+
+ /**
+ * Purge cache data
+ */
+ function purge()
+ {
+ // Purge all phpbb cache files
+ $dir = @opendir($this->cache_dir);
+
+ if (!$dir)
+ {
+ return;
+ }
+
+ while (($entry = readdir($dir)) !== false)
+ {
+ if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
+ {
+ continue;
+ }
+
+ $this->remove_file($this->cache_dir . $entry);
+ }
+ closedir($dir);
+
+ unset($this->vars);
+ unset($this->sql_rowset);
+ unset($this->sql_row_pointer);
+
+ $this->vars = array();
+ $this->sql_rowset = array();
+ $this->sql_row_pointer = array();
+
+ $this->is_modified = false;
+ }
+
+
+ /**
+ * Destroy cache data
+ */
+ function destroy($var_name, $table = '')
+ {
+ if ($var_name == 'sql' && !empty($table))
+ {
+ if (!is_array($table))
+ {
+ $table = array($table);
+ }
+
+ foreach ($table as $table_name)
+ {
+ // gives us the md5s that we want
+ $temp = $this->_read('sql_' . $table_name);
+
+ if ($temp === false)
+ {
+ continue;
+ }
+
+ // delete each query ref
+ foreach ($temp as $md5_id => $void)
+ {
+ $this->_delete('sql_' . $md5_id);
+ }
+
+ // delete the table ref
+ $this->_delete('sql_' . $table_name);
+ }
+
+ return;
+ }
+
+ if (!$this->_exists($var_name))
+ {
+ return;
+ }
+
+ if ($var_name[0] == '_')
+ {
+ $this->_delete($var_name);
+ }
+ else if (isset($this->vars[$var_name]))
+ {
+ $this->is_modified = true;
+ unset($this->vars[$var_name]);
+
+ // We save here to let the following cache hits succeed
+ $this->save();
+ }
+ }
+
+ /**
+ * Check if a given cache entry exist
+ */
+ function _exists($var_name)
+ {
+ if ($var_name[0] == '_')
+ {
+ return $this->_isset($var_name);
+ }
+ else
+ {
+ if (!sizeof($this->vars))
+ {
+ $this->load();
+ }
+
+ return isset($this->vars[$var_name]);
+ }
+ }
+
+ /**
+ * Load cached sql query
+ */
+ function sql_load($query)
+ {
+ // Remove extra spaces and tabs
+ $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
+ $query_id = sizeof($this->sql_rowset);
+
+ if (($result = $this->_read('sql_' . md5($query))) === false)
+ {
+ return false;
+ }
+
+ $this->sql_rowset[$query_id] = $result;
+ $this->sql_row_pointer[$query_id] = 0;
+
+ return $query_id;
+ }
+
+ /**
+ * Save sql query
+ */
+ function sql_save($query, &$query_result, $ttl)
+ {
+ global $db;
+
+ // Remove extra spaces and tabs
+ $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
+ $hash = md5($query);
+
+ // determine which tables this query belongs to
+ // Some queries use backticks, namely the get_database_size() query
+ // don't check for conformity, the SQL would error and not reach here.
+ if (!preg_match('/FROM \\(?(`?\\w+`?(?: \\w+)?(?:, ?`?\\w+`?(?: \\w+)?)*)\\)?/', $query, $regs))
+ {
+ // Bail out if the match fails.
+ return;
+ }
+ $tables = array_map('trim', explode(',', $regs[1]));
+
+ foreach ($tables as $table_name)
+ {
+ // Remove backticks
+ $table_name = ($table_name[0] == '`') ? substr($table_name, 1, -1) : $table_name;
+
+ if (($pos = strpos($table_name, ' ')) !== false)
+ {
+ $table_name = substr($table_name, 0, $pos);
+ }
+
+ $temp = $this->_read('sql_' . $table_name);
+
+ if ($temp === false)
+ {
+ $temp = array();
+ }
+
+ $temp[$hash] = true;
+
+ // This must never expire
+ $this->_write('sql_' . $table_name, $temp, 0);
+ }
+
+ // store them in the right place
+ $query_id = sizeof($this->sql_rowset);
+ $this->sql_rowset[$query_id] = array();
+ $this->sql_row_pointer[$query_id] = 0;
+
+ while ($row = $db->sql_fetchrow($query_result))
+ {
+ $this->sql_rowset[$query_id][] = $row;
+ }
+ $db->sql_freeresult($query_result);
+
+ $this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl);
+
+ $query_result = $query_id;
+ }
+
+ /**
+ * Ceck if a given sql query exist in cache
+ */
+ function sql_exists($query_id)
+ {
+ return isset($this->sql_rowset[$query_id]);
+ }
+
+ /**
+ * Fetch row from cache (database)
+ */
+ function sql_fetchrow($query_id)
+ {
+ if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id]))
+ {
+ return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++];
+ }
+
+ return false;
+ }
+
+ /**
+ * Fetch a field from the current row of a cached database result (database)
+ */
+ function sql_fetchfield($query_id, $field)
+ {
+ if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id]))
+ {
+ return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Seek a specific row in an a cached database result (database)
+ */
+ function sql_rowseek($rownum, $query_id)
+ {
+ if ($rownum >= sizeof($this->sql_rowset[$query_id]))
+ {
+ return false;
+ }
+
+ $this->sql_row_pointer[$query_id] = $rownum;
+ return true;
+ }
+
+ /**
+ * Free memory used for a cached database result (database)
+ */
+ function sql_freeresult($query_id)
+ {
+ if (!isset($this->sql_rowset[$query_id]))
+ {
+ return false;
+ }
+
+ unset($this->sql_rowset[$query_id]);
+ unset($this->sql_row_pointer[$query_id]);
+
+ return true;
+ }
+
+ /**
+ * Removes/unlinks file
+ */
+ function remove_file($filename, $check = false)
+ {
+ if ($check && !@is_writable($this->cache_dir))
+ {
+ // E_USER_ERROR - not using language entry - intended.
+ trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR);
+ }
+
+ return @unlink($filename);
+ }
+
+ /**
+ * Check if a cache var exists
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if it exists, otherwise false
+ */
+ function _isset($var)
+ {
+ // Most caches don't need to check
+ return true;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_null.php b/phpBB/includes/acm/acm_null.php
new file mode 100644
index 0000000000..fca67115a7
--- /dev/null
+++ b/phpBB/includes/acm/acm_null.php
@@ -0,0 +1,156 @@
+
\ No newline at end of file
diff --git a/phpBB/includes/acm/acm_xcache.php b/phpBB/includes/acm/acm_xcache.php
new file mode 100644
index 0000000000..d0a614660c
--- /dev/null
+++ b/phpBB/includes/acm/acm_xcache.php
@@ -0,0 +1,121 @@
+ 0
+* - xcache.admin.enable_auth = off (or xcache.admin.user and xcache.admin.password set)
+*
+*/
+class acm extends acm_memory
+{
+ var $extension = 'XCache';
+
+ function acm()
+ {
+ parent::acm_memory();
+
+ if (!function_exists('ini_get') || (int) ini_get('xcache.var_size') <= 0)
+ {
+ trigger_error('Increase xcache.var_size setting above 0 or enable ini_get() to use this ACM module.', E_USER_ERROR);
+ }
+ }
+
+ /**
+ * Purge cache data
+ *
+ * @return void
+ */
+ function purge()
+ {
+ // Run before for XCache, if admin functions are disabled it will terminate execution
+ parent::purge();
+
+ // If the admin authentication is enabled but not set up, this will cause a nasty error.
+ // Not much we can do about it though.
+ $n = xcache_count(XC_TYPE_VAR);
+
+ for ($i = 0; $i < $n; $i++)
+ {
+ xcache_clear_cache(XC_TYPE_VAR, $i);
+ }
+ }
+
+ /**
+ * Fetch an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return mixed Cached data
+ */
+ function _read($var)
+ {
+ $result = xcache_get($this->key_prefix . $var);
+
+ return ($result !== null) ? $result : false;
+ }
+
+ /**
+ * Store data in the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @param mixed $data Data to store
+ * @param int $ttl Time-to-live of cached data
+ * @return bool True if the operation succeeded
+ */
+ function _write($var, $data, $ttl = 2592000)
+ {
+ return xcache_set($this->key_prefix . $var, $data, $ttl);
+ }
+
+ /**
+ * Remove an item from the cache
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if the operation succeeded
+ */
+ function _delete($var)
+ {
+ return xcache_unset($this->key_prefix . $var);
+ }
+
+ /**
+ * Check if a cache var exists
+ *
+ * @access protected
+ * @param string $var Cache key
+ * @return bool True if it exists, otherwise false
+ */
+ function _isset($var)
+ {
+ return xcache_isset($this->key_prefix . $var);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php
index ef20b48cec..849c076f0e 100644
--- a/phpBB/includes/acp/acp_attachments.php
+++ b/phpBB/includes/acp/acp_attachments.php
@@ -684,8 +684,9 @@ class acp_attachments
$ext_group_row['max_filesize'] = (int) $config['max_filesize'];
}
- $size_format = ($ext_group_row['max_filesize'] >= 1048576) ? 'mb' : (($ext_group_row['max_filesize'] >= 1024) ? 'kb' : 'b');
- $ext_group_row['max_filesize'] = get_formatted_filesize($ext_group_row['max_filesize'], false);
+ $max_filesize = get_formatted_filesize($ext_group_row['max_filesize'], false, array('mb', 'kb', 'b'));
+ $size_format = $max_filesize['si_identifier'];
+ $ext_group_row['max_filesize'] = $max_filesize['value'];
$img_path = $config['upload_icons_path'];
@@ -694,7 +695,7 @@ class acp_attachments
$imglist = filelist($phpbb_root_path . $img_path);
- if (sizeof($imglist))
+ if (!empty($imglist['']))
{
$imglist = array_values($imglist);
$imglist = $imglist[0];
@@ -1026,8 +1027,8 @@ class acp_attachments
$template->assign_block_vars('orphan', array(
'FILESIZE' => get_formatted_filesize($row['filesize']),
'FILETIME' => $user->format_date($row['filetime']),
- 'REAL_FILENAME' => basename($row['real_filename']),
- 'PHYSICAL_FILENAME' => basename($row['physical_filename']),
+ 'REAL_FILENAME' => utf8_basename($row['real_filename']),
+ 'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']),
'ATTACH_ID' => $row['attach_id'],
'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id']))
@@ -1429,8 +1430,9 @@ class acp_attachments
function max_filesize($value, $key = '')
{
// Determine size var and adjust the value accordingly
- $size_var = ($value >= 1048576) ? 'mb' : (($value >= 1024) ? 'kb' : 'b');
- $value = get_formatted_filesize($value, false);
+ $filesize = get_formatted_filesize($value, false, array('mb', 'kb', 'b'));
+ $size_var = $filesize['si_identifier'];
+ $value = $filesize['value'];
return '
';
}
diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php
index 77fb44dda9..3198376584 100644
--- a/phpBB/includes/acp/acp_ban.php
+++ b/phpBB/includes/acp/acp_ban.php
@@ -156,7 +156,8 @@ class acp_ban
FROM ' . BANLIST_TABLE . '
WHERE (ban_end >= ' . time() . "
OR ban_end = 0)
- AND ban_ip <> ''";
+ AND ban_ip <> ''
+ ORDER BY ban_ip";
break;
case 'email':
@@ -168,7 +169,8 @@ class acp_ban
FROM ' . BANLIST_TABLE . '
WHERE (ban_end >= ' . time() . "
OR ban_end = 0)
- AND ban_email <> ''";
+ AND ban_email <> ''
+ ORDER BY ban_email";
break;
}
$result = $db->sql_query($sql);
@@ -181,7 +183,22 @@ class acp_ban
$banned_options .= '
';
$time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0;
- $ban_length[$row['ban_id']] = (isset($ban_end_text[$time_length])) ? $ban_end_text[$time_length] : $user->lang['UNTIL'] . ' -> ' . $user->format_date($row['ban_end']);
+
+ if ($time_length == 0)
+ {
+ // Banned permanently
+ $ban_length[$row['ban_id']] = $user->lang['PERMANENT'];
+ }
+ else if (isset($ban_end_text[$time_length]))
+ {
+ // Banned for a given duration
+ $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DURATION'], $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true));
+ }
+ else
+ {
+ // Banned until given date
+ $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DATE'], $user->format_date($row['ban_end'], false, true));
+ }
$ban_reasons[$row['ban_id']] = $row['ban_reason'];
$ban_give_reasons[$row['ban_id']] = $row['ban_give_reason'];
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index bce35ee68f..9f0bcf210f 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -64,6 +64,8 @@ class acp_board
'legend2' => 'WARNINGS',
'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -79,12 +81,14 @@ class acp_board
'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_pm_report' => array('lang' => 'ALLOW_PM_REPORT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'ACP_LOAD_SETTINGS',
'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -93,6 +97,8 @@ class acp_board
'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -108,9 +114,11 @@ class acp_board
'avatar_max_width' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,),
'avatar_max_height' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,),
+ 'allow_avatar' => array('lang' => 'ALLOW_AVATARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
@@ -143,7 +151,9 @@ class acp_board
'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false)
+ 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -162,26 +172,30 @@ class acp_board
'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'POSTING',
- 'enable_queue_trigger' => array('lang' => 'ENABLE_QUEUE_TRIGGER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'queue_trigger_posts' => array('lang' => 'QUEUE_TRIGGER_POSTS', 'validate' => 'int:0:250', 'type' => 'text:4:4', 'explain' => true),
'bump_type' => false,
'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'delete_time' => array('lang' => 'DELETE_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int:0', 'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int:0', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true),
'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
+ 'smilies_per_page' => array('lang' => 'SMILIES_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true),
'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false),
'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true),
+ 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true),
'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'),
'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -205,6 +219,8 @@ class acp_board
'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -218,6 +234,8 @@ class acp_board
'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),
'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true),
+ 'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']),
+ 'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true),
'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', 'type' => 'custom', 'method' => 'password_length', 'explain' => true),
'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'validate' => 'string', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true),
@@ -235,6 +253,28 @@ class acp_board
'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'coppa_mail' => array('lang' => 'COPPA_MAIL', 'validate' => 'string', 'type' => 'textarea:5:40', 'explain' => true),
'coppa_fax' => array('lang' => 'COPPA_FAX', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => false),
+
+ 'legend4' => 'ACP_SUBMIT_CHANGES',
+ )
+ );
+ break;
+
+ case 'feed':
+ $display_vars = array(
+ 'title' => 'ACP_FEED_MANAGEMENT',
+ 'vars' => array(
+ 'legend1' => 'ACP_FEED_GENERAL',
+ 'feed_enable' => array('lang' => 'ACP_FEED_ENABLE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
+ 'feed_item_statistics' => array('lang' => 'ACP_FEED_ITEM_STATISTICS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
+ 'feed_limit' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => true),
+ 'feed_overall_forums' => array('lang' => 'ACP_FEED_OVERALL_FORUMS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
+ 'feed_overall_forums_limit' => array('lang' => 'ACP_FEED_OVERALL_FORUMS_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false),
+ 'feed_overall_topics' => array('lang' => 'ACP_FEED_OVERALL_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
+ 'feed_overall_topics_limit' => array('lang' => 'ACP_FEED_OVERALL_TOPIC_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false),
+ 'feed_forum' => array('lang' => 'ACP_FEED_FORUM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
+ 'feed_topic' => array('lang' => 'ACP_FEED_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
+ 'feed_news_id' => array('lang' => 'ACP_FEED_NEWS', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_news_forums', 'explain' => true),
+ 'feed_exclude_id' => array('lang' => 'ACP_FEED_EXCLUDE_ID', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_exclude_forums', 'explain' => true),
)
);
break;
@@ -279,6 +319,8 @@ class acp_board
'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+
+ 'legend4' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -312,6 +354,8 @@ class acp_board
'server_name' => array('lang' => 'SERVER_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true),
'script_path' => array('lang' => 'SCRIPT_PATH', 'validate' => 'script_path', 'type' => 'text::255', 'explain' => true),
+
+ 'legend4' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -360,7 +404,9 @@ class acp_board
'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0', 'type' => 'text:4:5', 'explain' => true),
'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true),
'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true),
- 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true)
+ 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true),
+
+ 'legend3' => 'ACP_SUBMIT_CHANGES',
)
);
break;
@@ -400,7 +446,7 @@ class acp_board
continue;
}
- if ($config_name == 'auth_method')
+ if ($config_name == 'auth_method' || $config_name == 'feed_news_id' || $config_name == 'feed_exclude_id')
{
continue;
}
@@ -420,6 +466,13 @@ class acp_board
}
}
+ // Store news and exclude ids
+ if ($mode == 'feed' && $submit)
+ {
+ $this->store_feed_forums(FORUM_OPTION_FEED_NEWS, 'feed_news_id');
+ $this->store_feed_forums(FORUM_OPTION_FEED_EXCLUDE, 'feed_exclude_id');
+ }
+
if ($mode == 'auth')
{
// Retrieve a list of auth plugins and check their config values
@@ -830,6 +883,75 @@ class acp_board
return "
";
}
+
+ /**
+ * Select multiple forums
+ */
+ function select_news_forums($value, $key)
+ {
+ global $user, $config;
+
+ $forum_list = make_forum_select(false, false, true, true, true, false, true);
+
+ // Build forum options
+ $s_forum_options = '
';
+
+ return $s_forum_options;
+ }
+
+ function select_exclude_forums($value, $key)
+ {
+ global $user, $config;
+
+ $forum_list = make_forum_select(false, false, true, false, false, false, true);
+
+ // Build forum options
+ $s_forum_options = '
';
+
+ return $s_forum_options;
+ }
+
+ function store_feed_forums($option, $key)
+ {
+ global $db, $cache;
+
+ // Get key
+ $values = request_var($key, array(0 => 0));
+
+ // Empty option bit for all forums
+ $sql = 'UPDATE ' . FORUMS_TABLE . '
+ SET forum_options = forum_options - ' . (1 << $option) . '
+ WHERE ' . $db->sql_bit_and('forum_options', $option, '<> 0');
+ $db->sql_query($sql);
+
+ // Already emptied for all...
+ if (sizeof($values))
+ {
+ // Set for selected forums
+ $sql = 'UPDATE ' . FORUMS_TABLE . '
+ SET forum_options = forum_options + ' . (1 << $option) . '
+ WHERE ' . $db->sql_in_set('forum_id', $values);
+ $db->sql_query($sql);
+ }
+
+ // Empty sql cache for forums table because options changed
+ $cache->destroy('sql', FORUMS_TABLE);
+ }
+
}
?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index 93505e1590..6e86f412fb 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -28,108 +28,120 @@ class acp_captcha
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/board');
- $captcha_vars = array(
- 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID',
- 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID',
- 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE',
- 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED',
- 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE',
- 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE',
- 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS',
- );
+ include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
- if (isset($_GET['demo']))
+ $selected = request_var('select_captcha', $config['captcha_plugin']);
+ $configure = request_var('configure', false);
+
+ // Oh, they are just here for the view
+ if (isset($_GET['captcha_demo']))
{
- $captcha_vars = array_keys($captcha_vars);
-
- foreach ($captcha_vars as $captcha_var)
- {
- $config[$captcha_var] = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
- }
-
- if ($config['captcha_gd'])
- {
- include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
- }
- else
- {
- include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx);
- }
-
- $captcha = new captcha();
- $captcha->execute(gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)), time());
- exit;
+ $this->deliver_demo($selected);
}
- $config_vars = array(
- 'enable_confirm' => 'REG_ENABLE',
- 'enable_post_confirm' => 'POST_ENABLE',
- 'confirm_refresh' => 'CONFIRM_REFRESH',
- 'captcha_gd' => 'CAPTCHA_GD',
- );
-
- $this->tpl_name = 'acp_captcha';
- $this->page_title = 'ACP_VC_SETTINGS';
- $form_key = 'acp_captcha';
- add_form_key($form_key);
-
- $submit = request_var('submit', '');
-
- if ($submit && check_form_key($form_key))
+ // Delegate
+ if ($configure)
{
- $config_vars = array_keys($config_vars);
-
- foreach ($config_vars as $config_var)
- {
- set_config($config_var, request_var($config_var, ''));
- }
-
- $captcha_vars = array_keys($captcha_vars);
-
- foreach ($captcha_vars as $captcha_var)
- {
- $value = request_var($captcha_var, 0);
- if ($value >= 0)
- {
- set_config($captcha_var, $value);
- }
- }
-
+ $config_captcha =& phpbb_captcha_factory::get_instance($selected);
+ $config_captcha->acp_page($id, $this);
add_log('admin', 'LOG_CONFIG_VISUAL');
- trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
- }
- else if ($submit)
- {
- trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action));
}
else
{
- $preview_image_src = append_sid(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&demo=demo"));
+ $captchas = phpbb_captcha_factory::get_captcha_types();
- if (@extension_loaded('gd'))
+ $config_vars = array(
+ 'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false),
+ 'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false),
+ 'confirm_refresh' => array('tpl' => 'CONFIRM_REFRESH', 'default' => false),
+ 'max_reg_attempts' => array('tpl' => 'REG_LIMIT', 'default' => 0),
+ );
+
+ $this->tpl_name = 'acp_captcha';
+ $this->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('main_submit', false);
+
+ if ($submit && check_form_key($form_key))
{
- $template->assign_var('GD', true);
- }
+ foreach ($config_vars as $config_var => $options)
+ {
+ set_config($config_var, request_var($config_var, $options['default']));
+ }
- foreach ($config_vars as $config_var => $template_var)
+ if ($selected !== $config['captcha_plugin'])
+ {
+ // sanity check
+ if (isset($captchas['available'][$selected]))
+ {
+ $old_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $old_captcha->uninstall();
+
+ set_config('captcha_plugin', $selected);
+ $new_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $new_captcha->install();
+
+ add_log('admin', 'LOG_CONFIG_VISUAL');
+ }
+ else
+ {
+ trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action));
+ }
+ }
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
+ }
+ else if ($submit)
{
- $template->assign_var($template_var, (isset($_REQUEST[$config_var])) ? request_var($config_var, '') : $config[$config_var]) ;
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link());
}
-
- foreach ($captcha_vars as $captcha_var => $template_var)
+ else
{
- $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
- $template->assign_var($template_var, $var);
- $preview_image_src .= "&$captcha_var=" . $var;
- }
+ $captcha_select = '';
+ foreach ($captchas['available'] as $value => $title)
+ {
+ $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : '';
+ $captcha_select .= '
';
+ }
- $template->assign_vars(array(
- 'CAPTCHA_PREVIEW' => $preview_image_src,
- 'PREVIEW' => isset($_POST['preview']),
- ));
+ foreach ($captchas['unavailable'] as $value => $title)
+ {
+ $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : '';
+ $captcha_select .= '
';
+ }
+
+ $demo_captcha =& phpbb_captcha_factory::get_instance($selected);
+
+ foreach ($config_vars as $config_var => $options)
+ {
+ $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? request_var($config_var, $options['default']) : $config[$config_var]) ;
+ }
+
+ $template->assign_vars(array(
+ 'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
+ 'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
+ 'CAPTCHA_SELECT' => $captcha_select,
+ ));
+ }
}
}
+
+ /**
+ * Entry point for delivering image CAPTCHAs in the ACP.
+ */
+ function deliver_demo($selected)
+ {
+ global $db, $user, $config;
+
+ $captcha =& phpbb_captcha_factory::get_instance($selected);
+ $captcha->init(CONFIRM_REG);
+ $captcha->execute_demo();
+
+ garbage_collection();
+ exit_handler();
+ }
}
?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index 856b867c9a..b25518e1c4 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -548,7 +548,7 @@ class base_extractor
if (!$this->fp)
{
- trigger_error('Unable to write temporary file to storage folder', E_USER_ERROR);
+ trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
}
}
}
@@ -1157,16 +1157,17 @@ class postgres_extractor extends base_extractor
AND (c.oid = d.adrelid)
AND d.adnum = " . $row['attnum'];
$def_res = $db->sql_query($sql_get_default);
+ $def_row = $db->sql_fetchrow($def_res);
+ $db->sql_freeresult($def_res);
- if (!$def_res)
+ if (empty($def_row))
{
unset($row['rowdefault']);
}
else
{
- $row['rowdefault'] = $db->sql_fetchfield('rowdefault', false, $def_res);
+ $row['rowdefault'] = $def_row['rowdefault'];
}
- $db->sql_freeresult($def_res);
if ($row['type'] == 'bpchar')
{
@@ -1854,7 +1855,8 @@ class oracle_extractor extends base_extractor
// Build the SQL statement to recreate the data.
for ($i = 0; $i < $i_num_fields; $i++)
{
- $str_val = $row[$ary_name[$i]];
+ // Oracle uses uppercase - we use lowercase
+ $str_val = $row[strtolower($ary_name[$i])];
if (preg_match('#char|text|bool|raw#i', $ary_type[$i]))
{
@@ -1885,7 +1887,7 @@ class oracle_extractor extends base_extractor
}
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
- $schema_fields[$i] = '"' . $ary_name[$i] . "'";
+ $schema_fields[$i] = '"' . $ary_name[$i] . '"';
}
// Take the ordered fields and their associated data and build it
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index bf5242ace6..045d8a2e8e 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -75,6 +75,13 @@ class acp_forums
trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
}
+ case 'copy_perm':
+
+ if (!(($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))
+ {
+ trigger_error($user->lang['NO_PERMISSION_COPY'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
break;
}
@@ -118,6 +125,7 @@ class acp_forums
'type_action' => request_var('type_action', ''),
'forum_status' => request_var('forum_status', ITEM_UNLOCKED),
'forum_parents' => '',
+ 'forum_options' => 0,
'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)),
'forum_link' => request_var('forum_link', ''),
'forum_link_track' => request_var('forum_link_track', false),
@@ -139,6 +147,7 @@ class acp_forums
'enable_icons' => request_var('enable_icons', false),
'enable_prune' => request_var('enable_prune', false),
'enable_post_review' => request_var('enable_post_review', true),
+ 'enable_quick_reply' => request_var('enable_quick_reply', false),
'prune_days' => request_var('prune_days', 7),
'prune_viewed' => request_var('prune_viewed', 7),
'prune_freq' => request_var('prune_freq', 1),
@@ -181,73 +190,22 @@ class acp_forums
if (!sizeof($errors))
{
$forum_perm_from = request_var('forum_perm_from', 0);
+ $cache->destroy('sql', FORUMS_TABLE);
// Copy permissions?
if (!empty($forum_perm_from) && $forum_perm_from != $forum_data['forum_id'] &&
(($action != 'edit') || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))
{
- // if we edit a forum delete current permissions first
- if ($action == 'edit')
- {
- $sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
- WHERE forum_id = ' . (int) $forum_data['forum_id'];
- $db->sql_query($sql);
-
- $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
- WHERE forum_id = ' . (int) $forum_data['forum_id'];
- $db->sql_query($sql);
- }
-
- // From the mysql documentation:
- // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
- // Due to this we stay on the safe side if we do the insertion "the manual way"
-
- // Copy permisisons from/to the acl users table (only forum_id gets changed)
- $sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting
- FROM ' . ACL_USERS_TABLE . '
- WHERE forum_id = ' . $forum_perm_from;
- $result = $db->sql_query($sql);
-
- $users_sql_ary = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $users_sql_ary[] = array(
- 'user_id' => (int) $row['user_id'],
- 'forum_id' => (int) $forum_data['forum_id'],
- 'auth_option_id' => (int) $row['auth_option_id'],
- 'auth_role_id' => (int) $row['auth_role_id'],
- 'auth_setting' => (int) $row['auth_setting']
- );
- }
- $db->sql_freeresult($result);
-
- // Copy permisisons from/to the acl groups table (only forum_id gets changed)
- $sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting
- FROM ' . ACL_GROUPS_TABLE . '
- WHERE forum_id = ' . $forum_perm_from;
- $result = $db->sql_query($sql);
-
- $groups_sql_ary = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $groups_sql_ary[] = array(
- 'group_id' => (int) $row['group_id'],
- 'forum_id' => (int) $forum_data['forum_id'],
- 'auth_option_id' => (int) $row['auth_option_id'],
- 'auth_role_id' => (int) $row['auth_role_id'],
- 'auth_setting' => (int) $row['auth_setting']
- );
- }
- $db->sql_freeresult($result);
-
- // Now insert the data
- $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
- $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
+ copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false);
cache_moderators();
}
+ else if (($action != 'edit') && $auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))
+ {
+ $this->copy_permission_page($forum_data);
+ return;
+ }
$auth->acl_clear_prefetch();
- $cache->destroy('sql', FORUMS_TABLE);
$acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id'];
@@ -423,6 +381,7 @@ class acp_forums
$forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0;
$forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
$forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0;
+ $forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;
}
// Show form to create/modify a forum
@@ -485,6 +444,7 @@ class acp_forums
'prune_viewed' => 7,
'prune_freq' => 1,
'forum_flags' => FORUM_FLAG_POST_REVIEW,
+ 'forum_options' => 0,
'forum_password' => '',
'forum_password_confirm'=> '',
);
@@ -682,6 +642,7 @@ class acp_forums
'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false,
'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) ? true : false,
'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false,
+ 'S_ENABLE_QUICK_REPLY' => ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false,
'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false,
));
@@ -740,6 +701,32 @@ class acp_forums
return;
break;
+
+ case 'copy_perm':
+ $forum_perm_from = request_var('forum_perm_from', 0);
+
+ // Copy permissions?
+ if (!empty($forum_perm_from) && $forum_perm_from != $forum_id)
+ {
+ copy_forum_permissions($forum_perm_from, $forum_id, true);
+ cache_moderators();
+ $auth->acl_clear_prefetch();
+ $cache->destroy('sql', FORUMS_TABLE);
+
+ $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_id;
+
+ $message = $user->lang['FORUM_UPDATED'];
+
+ // Redirect to permissions
+ if ($auth->acl_get('a_fauth'))
+ {
+ $message .= '
' . sprintf($user->lang['REDIRECT_ACL'], '
', '');
+ }
+
+ trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id));
+ }
+
+ break;
}
// Default management page
@@ -941,6 +928,7 @@ class acp_forums
$forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
$forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
$forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
+ $forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
// Unset data that are not database fields
$forum_data_sql = $forum_data;
@@ -951,6 +939,7 @@ class acp_forums
unset($forum_data_sql['prune_sticky']);
unset($forum_data_sql['show_active']);
unset($forum_data_sql['enable_post_review']);
+ unset($forum_data_sql['enable_quick_reply']);
unset($forum_data_sql['forum_password_confirm']);
// What are we going to do tonight Brain? The same thing we do everynight,
@@ -1927,6 +1916,30 @@ class acp_forums
adm_page_footer();
}
+
+ /**
+ * Display copy permission page
+ */
+ function copy_permission_page($forum_data)
+ {
+ global $phpEx, $phpbb_admin_path, $template, $user;
+
+ $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id'];
+ $action = append_sid($this->u_action . "&parent_id={$this->parent_id}&f={$forum_data['forum_id']}&action=copy_perm");
+
+ $l_acl = sprintf($user->lang['COPY_TO_ACL'], '
', '');
+
+ $this->tpl_name = 'acp_forums_copy_perm';
+
+ $template->assign_vars(array(
+ 'U_ACL' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url),
+ 'L_ACL_LINK' => $l_acl,
+ 'L_BACK_LINK' => adm_back_link($this->u_action . '&parent_id=' . $this->parent_id),
+ 'S_COPY_ACTION' => $action,
+ 'S_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_data['forum_id'], false, false, false),
+ ));
+ }
+
}
?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 2ee5ded01d..3df61ff4e2 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -309,6 +309,7 @@ class acp_groups
'message_limit' => request_var('group_message_limit', 0),
'max_recipients' => request_var('group_max_recipients', 0),
'founder_manage' => 0,
+ 'skip_auth' => request_var('group_skip_auth', 0),
);
if ($user->data['user_type'] == USER_FOUNDER)
@@ -400,11 +401,26 @@ class acp_groups
// were made.
$group_attributes = array();
- $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients', 'founder_manage');
- foreach ($test_variables as $test)
+ $test_variables = array(
+ 'rank' => 'int',
+ 'colour' => 'string',
+ 'avatar' => 'string',
+ 'avatar_type' => 'int',
+ 'avatar_width' => 'int',
+ 'avatar_height' => 'int',
+ 'receive_pm' => 'int',
+ 'legend' => 'int',
+ 'message_limit' => 'int',
+ 'max_recipients'=> 'int',
+ 'founder_manage'=> 'int',
+ 'skip_auth' => 'int',
+ );
+
+ foreach ($test_variables as $test => $type)
{
if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test]))
{
+ settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
}
}
@@ -562,7 +578,7 @@ class acp_groups
'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0,
'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0,
'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '',
-
+ 'GROUP_SKIP_AUTH' => (!empty($group_row['group_skip_auth'])) ? ' checked="checked"' : '',
'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'],
'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'],
@@ -591,8 +607,7 @@ class acp_groups
'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=settings&name=group_colour'),
'U_ACTION' => "{$this->u_action}&action=$action&g=$group_id",
'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)),
- )
- );
+ ));
return;
break;
@@ -607,7 +622,7 @@ class acp_groups
$this->page_title = 'GROUP_MEMBERS';
// Grab the leaders - always, on every page...
- $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
+ $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug
WHERE ug.group_id = $group_id
AND u.user_id = ug.user_id
@@ -621,11 +636,12 @@ class acp_groups
'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&action=edit&u={$row['user_id']}"),
'USERNAME' => $row['username'],
+ 'USERNAME_COLOUR' => $row['user_colour'],
'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false,
'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ',
'USER_POSTS' => $row['user_posts'],
- 'USER_ID' => $row['user_id'])
- );
+ 'USER_ID' => $row['user_id'],
+ ));
}
$db->sql_freeresult($result);
@@ -662,7 +678,7 @@ class acp_groups
));
// Grab the members
- $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
+ $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug
WHERE ug.group_id = $group_id
AND u.user_id = ug.user_id
@@ -687,6 +703,7 @@ class acp_groups
'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&action=edit&u={$row['user_id']}"),
'USERNAME' => $row['username'],
+ 'USERNAME_COLOUR' => $row['user_colour'],
'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false,
'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ',
'USER_POSTS' => $row['user_posts'],
@@ -763,8 +780,7 @@ class acp_groups
'GROUP_NAME' => $group_name,
'TOTAL_MEMBERS' => $row['total_members'],
- )
- );
+ ));
}
}
}
diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php
index a88090cb25..8213c55ccb 100644
--- a/phpBB/includes/acp/acp_icons.php
+++ b/phpBB/includes/acp/acp_icons.php
@@ -89,6 +89,18 @@ class acp_icons
continue;
}
+ // adjust the width and height to be lower than 128px while perserving the aspect ratio
+ if ($img_size[0] > 127 && $img_size[0] > $img_size[1])
+ {
+ $img_size[1] = (int) ($img_size[1] * (127 / $img_size[0]));
+ $img_size[0] = 127;
+ }
+ else if ($img_size[1] > 127)
+ {
+ $img_size[0] = (int) ($img_size[0] * (127 / $img_size[1]));
+ $img_size[1] = 127;
+ }
+
$_images[$path . $img]['file'] = $path . $img;
$_images[$path . $img]['width'] = $img_size[0];
$_images[$path . $img]['height'] = $img_size[1];
@@ -168,19 +180,19 @@ class acp_icons
}
}
}
-
+
$sql = "SELECT *
FROM $table
ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC');
$result = $db->sql_query($sql);
-
+
$data = array();
$after = false;
$display = 0;
$order_lists = array('', '');
$add_order_lists = array('', '');
$display_count = 0;
-
+
while ($row = $db->sql_fetchrow($result))
{
if ($action == 'add')
@@ -231,15 +243,15 @@ class acp_icons
$data = $_images;
}
- $colspan = (($mode == 'smilies') ? '7' : '5');
+ $colspan = (($mode == 'smilies') ? 7 : 5);
$colspan += ($icon_id) ? 1 : 0;
$colspan += ($action == 'add') ? 2 : 0;
-
+
$template->assign_vars(array(
'S_EDIT' => true,
'S_SMILIES' => ($mode == 'smilies') ? true : false,
'S_ADD' => ($action == 'add') ? true : false,
-
+
'S_ORDER_LIST_DISPLAY' => $order_list . $order_lists[1],
'S_ORDER_LIST_UNDISPLAY' => $order_list . $order_lists[0],
'S_ORDER_LIST_DISPLAY_COUNT' => $display_count + 1,
@@ -286,10 +298,10 @@ class acp_icons
'S_ADD_CODE' => true,
'S_IMG_OPTIONS' => $smiley_options,
-
+
'S_ADD_ORDER_LIST_DISPLAY' => $add_order_list . $add_order_lists[1],
'S_ADD_ORDER_LIST_UNDISPLAY' => $add_order_list . $add_order_lists[0],
-
+
'IMG_SRC' => $phpbb_root_path . $img_path . '/' . $default_row['smiley_url'],
'IMG_PATH' => $img_path,
'PHPBB_ROOT_PATH' => $phpbb_root_path,
@@ -303,7 +315,7 @@ class acp_icons
}
return;
-
+
break;
case 'create':
@@ -311,7 +323,7 @@ class acp_icons
// Get items to create/modify
$images = (isset($_POST['image'])) ? array_keys(request_var('image', array('' => 0))) : array();
-
+
// Now really get the items
$image_id = (isset($_POST['id'])) ? request_var('id', array('' => 0)) : array();
$image_order = (isset($_POST['order'])) ? request_var('order', array('' => 0)) : array();
@@ -348,6 +360,25 @@ class acp_icons
}
}
+ if ($mode == 'smilies' && $action == 'create')
+ {
+ $smiley_count = $this->item_count($table);
+
+ $addable_smileys_count = sizeof($images);
+ foreach ($images as $image)
+ {
+ if (!isset($image_add[$image]))
+ {
+ --$addable_smileys_count;
+ }
+ }
+
+ if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT)
+ {
+ trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+ }
+
$icons_updated = 0;
$errors = array();
foreach ($images as $image)
@@ -369,6 +400,17 @@ class acp_icons
$image_height[$image] = $img_size[1];
}
+ if ($image_width[$image] > 127 && $image_width[$image] > $image_height[$image])
+ {
+ $image_height[$image] = (int) ($image_height[$image] * (127 / $image_width[$image]));
+ $image_width[$image] = 127;
+ }
+ else if ($image_height[$image] > 127)
+ {
+ $image_width[$image] = (int) ($image_width[$image] * (127 / $image_height[$image]));
+ $image_height[$image] = 127;
+ }
+
$img_sql = array(
$fields . '_url' => $image,
$fields . '_width' => $image_width[$image],
@@ -426,13 +468,13 @@ class acp_icons
$db->sql_query($sql);
$icons_updated++;
}
-
+
}
}
-
+
$cache->destroy('_icons');
$cache->destroy('sql', $table);
-
+
$level = E_USER_NOTICE;
switch ($icons_updated)
{
@@ -440,11 +482,11 @@ class acp_icons
$suc_lang = "{$lang}_NONE";
$level = E_USER_WARNING;
break;
-
+
case 1:
$suc_lang = "{$lang}_ONE";
break;
-
+
default:
$suc_lang = $lang;
}
@@ -495,7 +537,6 @@ class acp_icons
}
}
-
// The user has already selected a smilies_pak file
if ($current == 'delete')
{
@@ -541,6 +582,15 @@ class acp_icons
$db->sql_freeresult($result);
}
+ if ($mode == 'smilies')
+ {
+ $smiley_count = $this->item_count($table);
+ if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT)
+ {
+ trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+ }
+
foreach ($pak_ary as $pak_entry)
{
$data = array();
@@ -835,11 +885,14 @@ class acp_icons
);
$spacer = false;
+ $pagination_start = request_var('start', 0);
+
+ $item_count = $this->item_count($table);
$sql = "SELECT *
FROM $table
ORDER BY {$fields}_order ASC";
- $result = $db->sql_query($sql);
+ $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $pagination_start);
while ($row = $db->sql_fetchrow($result))
{
@@ -855,9 +908,9 @@ class acp_icons
'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '',
'U_EDIT' => $this->u_action . '&action=edit&id=' . $row[$fields . '_id'],
'U_DELETE' => $this->u_action . '&action=delete&id=' . $row[$fields . '_id'],
- 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'],
- 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'])
- );
+ 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start,
+ 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start,
+ ));
if (!$spacer && !$row['display_on_posting'])
{
@@ -865,6 +918,28 @@ class acp_icons
}
}
$db->sql_freeresult($result);
+
+ $template->assign_var('PAGINATION',
+ generate_pagination($this->u_action, $item_count, $config['smilies_per_page'], $pagination_start, true)
+ );
+ }
+
+ /**
+ * Returns the count of smilies or icons in the database
+ *
+ * @param string $table The table of items to count.
+ * @return int number of items
+ */
+ /* private */ function item_count($table)
+ {
+ global $db;
+
+ $sql = "SELECT COUNT(*) AS count
+ FROM $table";
+ $result = $db->sql_query($sql);
+ $item_count = (int) $db->sql_fetchfield('count');
+ $db->sql_freeresult($result);
+ return $item_count;
}
}
diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php
index a38b47a704..3d0c0a2780 100644
--- a/phpBB/includes/acp/acp_inactive.php
+++ b/phpBB/includes/acp/acp_inactive.php
@@ -51,6 +51,19 @@ class acp_inactive
$form_key = 'acp_inactive';
add_form_key($form_key);
+ // We build the sort key and per page settings here, because they may be needed later
+
+ // Number of entries to display
+ $per_page = request_var('users_per_page', (int) $config['topics_per_page']);
+
+ // Sorting
+ $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
+ $sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'd' => $user->lang['SORT_LAST_REMINDER'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME'], 'p' => $user->lang['SORT_POSTS'], 'e' => $user->lang['SORT_REMINDER']);
+ $sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'd' => 'user_reminded_time', 'r' => 'user_inactive_reason', 'u' => 'username_clean', 'p' => 'user_posts', 'e' => 'user_reminded');
+
+ $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
+ gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
+
if ($submit && sizeof($mark))
{
if ($action !== 'delete' && !check_form_key($form_key))
@@ -67,7 +80,7 @@ class acp_inactive
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $mark);
$result = $db->sql_query($sql);
-
+
$user_affected = array();
while ($row = $db->sql_fetchrow($result))
{
@@ -100,7 +113,7 @@ class acp_inactive
{
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $messenger = new messenger();
+ $messenger = new messenger(false);
foreach ($inactive_users as $row)
{
@@ -122,6 +135,12 @@ class acp_inactive
$messenger->save_queue();
}
+
+ // For activate we really need to redirect, else a refresh can result in users being deactivated again
+ $u_action = $this->u_action . "&$u_sort_param&start=$start";
+ $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : '';
+
+ redirect($u_action);
}
else if ($action == 'delete')
{
@@ -175,7 +194,7 @@ class acp_inactive
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
- $usernames = array();
+ $usernames = $user_ids = array();
do
{
@@ -198,28 +217,34 @@ class acp_inactive
$messenger->send($row['user_notify_type']);
$usernames[] = $row['username'];
+ $user_ids[] = (int) $row['user_id'];
}
while ($row = $db->sql_fetchrow($result));
$messenger->save_queue();
+ // Add the remind state to the database
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_reminded = user_reminded + 1,
+ user_reminded_time = ' . time() . '
+ WHERE ' . $db->sql_in_set('user_id', $user_ids);
+ $db->sql_query($sql);
+
add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames));
unset($usernames);
}
$db->sql_freeresult($result);
-
+
+ // For remind we really need to redirect, else a refresh can result in more than one reminder
+ $u_action = $this->u_action . "&$u_sort_param&start=$start";
+ $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : '';
+
+ redirect($u_action);
+
break;
}
}
- // Sorting
- $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
- $sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME']);
- $sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'r' => 'user_inactive_reason', 'u' => 'username_clean');
-
- $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
- gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
-
// Define where and sort sql for use in displaying logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
@@ -227,19 +252,30 @@ class acp_inactive
$inactive = array();
$inactive_count = 0;
- $start = view_inactive_users($inactive, $inactive_count, $config['topics_per_page'], $start, $sql_where, $sql_sort);
+ $start = view_inactive_users($inactive, $inactive_count, $per_page, $start, $sql_where, $sql_sort);
foreach ($inactive as $row)
{
$template->assign_block_vars('inactive', array(
'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
+ 'REMINDED_DATE' => $user->format_date($row['user_reminded_time']),
'JOINED' => $user->format_date($row['user_regdate']),
'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
+
'REASON' => $row['inactive_reason'],
'USER_ID' => $row['user_id'],
- 'USERNAME' => $row['username'],
- 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"))
- );
+ 'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
+ 'REMINDED' => $row['user_reminded'],
+
+ 'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
+
+ 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')),
+ 'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
+ 'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
+
+ 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"),
+ 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '',
+ ));
}
$option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
@@ -255,9 +291,10 @@ class acp_inactive
'S_LIMIT_DAYS' => $s_limit_days,
'S_SORT_KEY' => $s_sort_key,
'S_SORT_DIR' => $s_sort_dir,
- 'S_ON_PAGE' => on_page($inactive_count, $config['topics_per_page'], $start),
- 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $inactive_count, $config['topics_per_page'], $start, true),
-
+ 'S_ON_PAGE' => on_page($inactive_count, $per_page, $start),
+ 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param&users_per_page=$per_page", $inactive_count, $per_page, $start, true),
+ 'USERS_PER_PAGE' => $per_page,
+
'U_ACTION' => $this->u_action . '&start=' . $start,
));
diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php
index 71970b4b50..8ca45a27f6 100644
--- a/phpBB/includes/acp/acp_language.php
+++ b/phpBB/includes/acp/acp_language.php
@@ -766,28 +766,41 @@ class acp_language
trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
+ if (confirm_box(true))
+ {
+ $db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
- WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
- $db->sql_query($sql);
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
+ WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
+ $db->sql_query($sql);
- // We also need to remove the translated entries for custom profile fields - we want clean tables, don't we?
- $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
- $db->sql_query($sql);
+ // We also need to remove the translated entries for custom profile fields - we want clean tables, don't we?
+ $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
+ $db->sql_query($sql);
- $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
- $db->sql_query($sql);
+ $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
+ $db->sql_query($sql);
- $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
- $result = $db->sql_query($sql);
+ $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
+ $result = $db->sql_query($sql);
- $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
+ $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE);
- add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
+ add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
- trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
+ trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
+ }
+ else
+ {
+ $s_hidden_fields = array(
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action,
+ 'id' => $lang_id,
+ );
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
+ }
break;
case 'install':
@@ -1254,7 +1267,7 @@ $lang = array_merge($lang, array(
$keys = func_get_args();
$non_static = array_shift($keys);
- $value = array_shift($keys);
+ $value = utf8_normalize_nfc(array_shift($keys));
if (!$non_static)
{
diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php
index 12953173f1..0f4f78fcdd 100644
--- a/phpBB/includes/acp/acp_logs.php
+++ b/phpBB/includes/acp/acp_logs.php
@@ -33,6 +33,7 @@ class acp_logs
// Set up general vars
$action = request_var('action', '');
$forum_id = request_var('f', 0);
+ $topic_id = request_var('t', 0);
$start = request_var('start', 0);
$deletemark = (!empty($_POST['delmarked'])) ? true : false;
$deleteall = (!empty($_POST['delall'])) ? true : false;
@@ -104,6 +105,9 @@ class acp_logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
+ $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
+
$l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS'];
$l_title_explain = $user->lang['ACP_' . strtoupper($mode) . '_LOGS_EXPLAIN'];
@@ -123,7 +127,7 @@ class acp_logs
// Grab log data
$log_data = array();
$log_count = 0;
- view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort);
+ view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords);
$template->assign_vars(array(
'L_TITLE' => $l_title,
@@ -131,12 +135,13 @@ class acp_logs
'U_ACTION' => $this->u_action,
'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start),
- 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $log_count, $config['topics_per_page'], $start, true),
+ 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true),
'S_LIMIT_DAYS' => $s_limit_days,
'S_SORT_KEY' => $s_sort_key,
'S_SORT_DIR' => $s_sort_dir,
'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'),
+ 'S_KEYWORDS' => $keywords,
)
);
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index 8a92c06e04..cd83c52e01 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -97,6 +97,10 @@ class acp_main
$confirm = true;
$confirm_lang = 'PURGE_CACHE_CONFIRM';
break;
+ case 'purge_sessions':
+ $confirm = true;
+ $confirm_lang = 'PURGE_SESSIONS_CONFIRM';
+ break;
default:
$confirm = true;
@@ -341,10 +345,76 @@ class acp_main
add_log('admin', 'LOG_PURGE_CACHE');
break;
+
+ case 'purge_sessions':
+ if ((int) $user->data['user_type'] !== USER_FOUNDER)
+ {
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
+ $tables = array(CONFIRM_TABLE, SESSIONS_TABLE);
+
+ foreach ($tables as $table)
+ {
+ switch ($db->sql_layer)
+ {
+ case 'sqlite':
+ case 'firebird':
+ $db->sql_query("DELETE FROM $table");
+ break;
+
+ default:
+ $db->sql_query("TRUNCATE TABLE $table");
+ break;
+ }
+ }
+
+ // let's restore the admin session
+ $reinsert_ary = array(
+ 'session_id' => (string) $user->session_id,
+ 'session_page' => (string) substr($user->page['page'], 0, 199),
+ 'session_forum_id' => $user->page['forum'],
+ 'session_user_id' => (int) $user->data['user_id'],
+ 'session_start' => (int) $user->data['session_start'],
+ 'session_last_visit' => (int) $user->data['session_last_visit'],
+ 'session_time' => (int) $user->time_now,
+ 'session_browser' => (string) trim(substr($user->browser, 0, 149)),
+ 'session_forwarded_for' => (string) $user->forwarded_for,
+ 'session_ip' => (string) $user->ip,
+ 'session_autologin' => (int) $user->data['session_autologin'],
+ 'session_admin' => 1,
+ 'session_viewonline' => (int) $user->data['session_viewonline'],
+ );
+
+ $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary);
+ $db->sql_query($sql);
+
+ add_log('admin', 'LOG_PURGE_SESSIONS');
+ break;
}
}
}
+ // Version check
+ $user->add_lang('install');
+
+ $latest_version_info = false;
+ if (($latest_version_info = obtain_latest_version_info(request_var('versioncheck_force', false))) === false)
+ {
+ $template->assign_var('S_VERSIONCHECK_FAIL', true);
+ }
+ else
+ {
+ $latest_version_info = explode("\n", $latest_version_info);
+
+ $latest_version = str_replace('rc', 'RC', strtolower(trim($latest_version_info[0])));
+ $current_version = str_replace('rc', 'RC', strtolower($config['version']));
+
+ $template->assign_vars(array(
+ 'S_VERSION_UP_TO_DATE' => version_compare($current_version, $latest_version, '<') ? false : true,
+ ));
+ }
+
// Get forum statistics
$total_posts = $config['num_posts'];
$total_topics = $config['num_topics'];
@@ -435,13 +505,15 @@ class acp_main
'UPLOAD_DIR_SIZE' => $upload_dir_size,
'TOTAL_ORPHAN' => $total_orphan,
'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true,
- 'GZIP_COMPRESSION' => ($config['gzip_compress']) ? $user->lang['ON'] : $user->lang['OFF'],
+ 'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'],
'DATABASE_INFO' => $db->sql_server_info(),
'BOARD_VERSION' => $config['version'],
'U_ACTION' => $this->u_action,
'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&mode=admin'),
'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&mode=list'),
+ 'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&mode=version_check'),
+ 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=1&versioncheck_force=1'),
'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false,
'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false,
@@ -468,6 +540,8 @@ class acp_main
if ($auth->acl_get('a_user'))
{
+ $user->add_lang('memberlist');
+
$inactive = array();
$inactive_count = 0;
@@ -477,13 +551,24 @@ class acp_main
{
$template->assign_block_vars('inactive', array(
'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
+ 'REMINDED_DATE' => $user->format_date($row['user_reminded_time']),
'JOINED' => $user->format_date($row['user_regdate']),
'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
+
'REASON' => $row['inactive_reason'],
'USER_ID' => $row['user_id'],
- 'USERNAME' => $row['username'],
- 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"))
- );
+ 'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
+ 'REMINDED' => $row['user_reminded'],
+
+ 'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
+
+ 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')),
+ 'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
+ 'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
+
+ 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"),
+ 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '',
+ ));
}
$option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
@@ -499,12 +584,12 @@ class acp_main
}
// Warn if install is still present
- if (file_exists($phpbb_root_path . 'install'))
+ if (file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
{
$template->assign_var('S_REMOVE_INSTALL', true);
}
- if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writable($phpbb_root_path . 'config.' . $phpEx))
+ if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx))
{
// World-Writable? (000x)
$template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002));
diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php
index 164970b5d5..e9f0af5071 100644
--- a/phpBB/includes/acp/acp_permissions.php
+++ b/phpBB/includes/acp/acp_permissions.php
@@ -57,6 +57,21 @@ class acp_permissions
trigger_error('NO_MODE', E_USER_ERROR);
}
+ // Copy forum permissions
+ if ($mode == 'setting_forum_copy')
+ {
+ $this->tpl_name = 'permission_forum_copy';
+
+ if ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))
+ {
+ $this->page_title = 'ACP_FORUM_PERMISSIONS_COPY';
+ $this->copy_forum_permissions();
+ return;
+ }
+
+ trigger_error('NO_MODE', E_USER_ERROR);
+ }
+
// Set some vars
$action = request_var('action', array('' => 0));
$action = key($action);
@@ -217,43 +232,71 @@ class acp_permissions
trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
// Handle actions
if (strpos($mode, 'setting_') === 0 && $action)
{
switch ($action)
{
case 'delete':
-
- if (!check_form_key($form_name))
+ if (confirm_box(true))
{
- trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
- }
- // All users/groups selected?
- $all_users = (isset($_POST['all_users'])) ? true : false;
- $all_groups = (isset($_POST['all_groups'])) ? true : false;
+ // All users/groups selected?
+ $all_users = (isset($_POST['all_users'])) ? true : false;
+ $all_groups = (isset($_POST['all_groups'])) ? true : false;
- if ($all_users || $all_groups)
- {
- $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type);
-
- if ($all_users && sizeof($items['user_ids']))
+ if ($all_users || $all_groups)
{
- $user_id = $items['user_ids'];
- }
- else if ($all_groups && sizeof($items['group_ids']))
- {
- $group_id = $items['group_ids'];
- }
- }
+ $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type);
- if (sizeof($user_id) || sizeof($group_id))
- {
- $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id);
+ if ($all_users && sizeof($items['user_ids']))
+ {
+ $user_id = $items['user_ids'];
+ }
+ else if ($all_groups && sizeof($items['group_ids']))
+ {
+ $group_id = $items['group_ids'];
+ }
+ }
+
+ if (sizeof($user_id) || sizeof($group_id))
+ {
+ $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id);
+ }
+ else
+ {
+ trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
}
else
{
- trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
+ if (isset($_POST['cancel']))
+ {
+ $u_redirect = $this->u_action . '&type=' . $permission_type;
+ foreach ($forum_id as $fid)
+ {
+ $u_redirect .= '&forum_id[]=' . $fid;
+ }
+ redirect($u_redirect);
+ }
+
+ $s_hidden_fields = array(
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => array($action => 1),
+ 'user_id' => $user_id,
+ 'group_id' => $group_id,
+ 'forum_id' => $forum_id,
+ 'type' => $permission_type,
+ );
+ if (isset($_POST['all_users']))
+ {
+ $s_hidden_fields['all_users'] = 1;
+ }
+ if (isset($_POST['all_groups']))
+ {
+ $s_hidden_fields['all_groups'] = 1;
+ }
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
break;
@@ -963,6 +1006,7 @@ class acp_permissions
LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (ug.group_id = g.group_id)
WHERE ug.user_id = ' . $user_id . '
AND ug.user_pending = 0
+ AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
ORDER BY g.group_type DESC, g.group_id DESC';
$result = $db->sql_query($sql);
@@ -1123,6 +1167,57 @@ class acp_permissions
));
}
+ /**
+ * Handles copying permissions from one forum to others
+ */
+ function copy_forum_permissions()
+ {
+ global $auth, $cache, $template, $user;
+
+ $user->add_lang('acp/forums');
+
+ $submit = isset($_POST['submit']) ? true : false;
+
+ if ($submit)
+ {
+ $src = request_var('src_forum_id', 0);
+ $dest = request_var('dest_forum_ids', array(0));
+
+ if (confirm_box(true))
+ {
+ if (copy_forum_permissions($src, $dest))
+ {
+ cache_moderators();
+
+ $auth->acl_clear_prefetch();
+ $cache->destroy('sql', FORUMS_TABLE);
+
+ trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action));
+ }
+ else
+ {
+ trigger_error($user->lang['SELECTED_FORUM_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+ }
+ else
+ {
+ $s_hidden_fields = array(
+ 'submit' => $submit,
+ 'src_forum_id' => $src,
+ 'dest_forum_ids' => $dest,
+ );
+
+ $s_hidden_fields = build_hidden_fields($s_hidden_fields);
+
+ confirm_box(false, $user->lang['COPY_PERMISSIONS_CONFIRM'], $s_hidden_fields);
+ }
+ }
+
+ $template->assign_vars(array(
+ 'S_FORUM_OPTIONS' => make_forum_select(false, false, false, false, false),
+ ));
+ }
+
/**
* Get already assigned users/groups
*/
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index bbe36af9be..1b0ec4b5d5 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -369,6 +369,7 @@ class acp_profile
'field_show_profile'=> 0,
'field_no_view' => 0,
'field_show_on_reg' => 0,
+ 'field_show_on_vt' => 0,
'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)),
'lang_explain' => '',
'lang_default_value'=> '')
@@ -379,7 +380,7 @@ class acp_profile
// $exclude contains the data we gather in each step
$exclude = array(
- 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'),
+ 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'),
2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'),
3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options')
);
@@ -405,6 +406,7 @@ class acp_profile
$visibility_ary = array(
'field_required',
'field_show_on_reg',
+ 'field_show_on_vt',
'field_show_profile',
'field_hide',
);
@@ -721,6 +723,7 @@ class acp_profile
'S_STEP_ONE' => true,
'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false,
'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false,
+ 'S_SHOW_ON_VT' => ($cp->vars['field_show_on_vt']) ? true : false,
'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false,
'S_SHOW_PROFILE' => ($cp->vars['field_show_profile']) ? true : false,
'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false,
@@ -1036,6 +1039,7 @@ class acp_profile
'field_validation' => $cp->vars['field_validation'],
'field_required' => $cp->vars['field_required'],
'field_show_on_reg' => $cp->vars['field_show_on_reg'],
+ 'field_show_on_vt' => $cp->vars['field_show_on_vt'],
'field_hide' => $cp->vars['field_hide'],
'field_show_profile' => $cp->vars['field_show_profile'],
'field_no_view' => $cp->vars['field_no_view']
diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php
index a82a438db7..7eeb37133f 100644
--- a/phpBB/includes/acp/acp_prune.php
+++ b/phpBB/includes/acp/acp_prune.php
@@ -406,7 +406,12 @@ class acp_prune
$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : '';
$where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';
- if (sizeof($active) && $active_select != 'lt')
+ // First handle pruning of users who never logged in, last active date is 0000-00-00
+ if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0)
+ {
+ $where_sql .= ' AND user_lastvisit = 0';
+ }
+ else if (sizeof($active) && $active_select != 'lt')
{
$where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]);
}
diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php
index 41ed5b0fba..fcfef2a61e 100644
--- a/phpBB/includes/acp/acp_ranks.php
+++ b/phpBB/includes/acp/acp_ranks.php
@@ -39,7 +39,7 @@ class acp_ranks
$this->tpl_name = 'acp_ranks';
$this->page_title = 'ACP_MANAGE_RANKS';
- $form_name = 'acp_prune';
+ $form_name = 'acp_ranks';
add_form_key($form_name);
switch ($action)
@@ -168,25 +168,22 @@ class acp_ranks
{
$img = $path . $img;
- if (!in_array($img, $existing_imgs) || $action == 'edit')
+ if ($ranks && $img == $ranks['rank_image'])
{
- if ($ranks && $img == $ranks['rank_image'])
- {
- $selected = ' selected="selected"';
- $edit_img = $img;
- }
- else
- {
- $selected = '';
- }
-
- if (strlen($img) > 255)
- {
- continue;
- }
-
- $filename_list .= '
';
+ $selected = ' selected="selected"';
+ $edit_img = $img;
}
+ else
+ {
+ $selected = '';
+ }
+
+ if (strlen($img) > 255)
+ {
+ continue;
+ }
+
+ $filename_list .= '
';
}
}
diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php
new file mode 100644
index 0000000000..b3baf54983
--- /dev/null
+++ b/phpBB/includes/acp/acp_send_statistics.php
@@ -0,0 +1,90 @@
+tpl_name = 'acp_send_statistics';
+ $this->page_title = 'ACP_SEND_STATISTICS';
+
+ // generate a unique id if necessary
+ if (!isset($config['questionnaire_unique_id']))
+ {
+ $install_id = unique_id();
+ set_config('questionnaire_unique_id', $install_id);
+ }
+ else
+ {
+ $install_id = $config['questionnaire_unique_id'];
+ }
+
+ $collector = new phpbb_questionnaire_data_collector($install_id);
+
+ // Add data provider
+ $collector->add_data_provider(new phpbb_questionnaire_php_data_provider());
+ $collector->add_data_provider(new phpbb_questionnaire_system_data_provider());
+ $collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config));
+
+ $template->assign_vars(array(
+ 'U_COLLECT_STATS' => $collect_url,
+ 'RAW_DATA' => $collector->get_data_for_form(),
+ 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"),
+ ));
+
+ $raw = $collector->get_data_raw();
+
+ foreach ($raw as $provider => $data)
+ {
+ if ($provider == 'install_id')
+ {
+ $data = array($provider => $data);
+ }
+
+ $template->assign_block_vars('providers', array(
+ 'NAME' => htmlspecialchars($provider),
+ ));
+
+ foreach ($data as $key => $value)
+ {
+ if (is_array($value))
+ {
+ $value = utf8_wordwrap(serialize($value), 75, "\n", true);
+ }
+
+ $template->assign_block_vars('providers.values', array(
+ 'KEY' => utf8_htmlspecialchars($key),
+ 'VALUE' => utf8_htmlspecialchars($value),
+ ));
+ }
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index 184c40f218..fbf3eadcb2 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -210,23 +210,36 @@ parse_css_file = {PARSE_CSS_FILE}
trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $sql = 'UPDATE ' . STYLES_TABLE . '
- SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
- WHERE style_id = ' . $style_id;
- $db->sql_query($sql);
-
- // Set style to default for any member using deactivated style
- if ($action == 'deactivate')
+ if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate')
{
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_style = ' . $config['default_style'] . "
- WHERE user_style = $style_id";
+ $sql = 'UPDATE ' . STYLES_TABLE . '
+ SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
+ WHERE style_id = ' . $style_id;
$db->sql_query($sql);
- $sql = 'UPDATE ' . FORUMS_TABLE . '
- SET forum_style = 0
- WHERE forum_style = ' . $style_id;
- $db->sql_query($sql);
+ // Set style to default for any member using deactivated style
+ if ($action == 'deactivate')
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_style = ' . $config['default_style'] . "
+ WHERE user_style = $style_id";
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . FORUMS_TABLE . '
+ SET forum_style = 0
+ WHERE forum_style = ' . $style_id;
+ $db->sql_query($sql);
+ }
+ }
+ else if ($action == 'deactivate')
+ {
+ $s_hidden_fields = array(
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action,
+ 'style_id' => $style_id,
+ );
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
}
break;
}
@@ -734,7 +747,8 @@ parse_css_file = {PARSE_CSS_FILE}
{
if (!($fp = @fopen($file, 'wb')))
{
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
+ // File exists and is writeable, but still not able to be written to
+ trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING);
}
fwrite($fp, $template_data);
fclose($fp);
@@ -827,6 +841,11 @@ parse_css_file = {PARSE_CSS_FILE}
unset($file_info);
}
+ if (empty($filelist['']))
+ {
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
// Now create the categories
$filelist_cats[''] = array();
foreach ($filelist as $pathfile => $file_ary)
@@ -1024,12 +1043,12 @@ parse_css_file = {PARSE_CSS_FILE}
foreach ($file_ary as $file)
{
- $file = str_replace('/', '.', $file);
+ $file = str_replace('/', '.', $file);
// perform some dirty guessing to get the path right.
// We assume that three dots in a row were '../'
- $tpl_file = str_replace('.', '/', $file);
- $tpl_file = str_replace('///', '../', $tpl_file);
+ $tpl_file = str_replace('.', '/', $file);
+ $tpl_file = str_replace('///', '../', $tpl_file);
$filename = "{$cache_prefix}_$file.html.$phpEx";
@@ -1061,6 +1080,11 @@ parse_css_file = {PARSE_CSS_FILE}
}
}
+ // Correct the filename if it is stored in database and the file is in a subfolder.
+ if ($template_row['template_storedb'])
+ {
+ $file = str_replace('.', '/', $file);
+ }
$template->assign_block_vars('file', array(
'U_VIEWSOURCE' => $this->u_action . "&action=cache&id=$template_id&source=$file",
@@ -1068,7 +1092,7 @@ parse_css_file = {PARSE_CSS_FILE}
'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
'FILENAME' => $file,
'FILENAME_PATH' => $file_tpl,
- 'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize("{$phpbb_root_path}cache/$filename") / 1024),
+ 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")),
'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html']))
);
}
@@ -1266,7 +1290,6 @@ parse_css_file = {PARSE_CSS_FILE}
);
}
-
/**
* Edit imagesets
*
@@ -2404,7 +2427,6 @@ parse_css_file = {PARSE_CSS_FILE}
}
}
-
if ($mode == 'template')
{
$super = array();
@@ -2535,9 +2557,22 @@ parse_css_file = {PARSE_CSS_FILE}
{
trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR);
}
- $template_data = fread($fp, filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"));
+
+ $filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file");
+
+ if ($filesize)
+ {
+ $template_data = fread($fp, $filesize);
+ }
+
fclose($fp);
+ if (!$filesize)
+ {
+ // File is empty
+ continue;
+ }
+
if (preg_match_all('##is', $template_data, $matches))
{
foreach ($matches[1] as $match)
@@ -3204,7 +3239,6 @@ parse_css_file = {PARSE_CSS_FILE}
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
-
if ($row)
{
// If it exist, we just use the style on installation
@@ -3255,7 +3289,6 @@ parse_css_file = {PARSE_CSS_FILE}
$inherit_bf = false;
}
-
if (sizeof($error))
{
return false;
@@ -3525,7 +3558,6 @@ parse_css_file = {PARSE_CSS_FILE}
break;
}
-
$sql = "SELECT {$mode}_inherits_id
FROM $sql_from
WHERE {$mode}_id = " . (int) $id;
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index dbb25bdbbd..121c72aeb3 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -37,12 +37,7 @@ class acp_update
$errstr = '';
$errno = 0;
- $info = get_remote_file('www.phpbb.com', '/updatecheck', ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
-
- if ($info === false)
- {
- trigger_error($errstr, E_USER_WARNING);
- }
+ $info = obtain_latest_version_info(request_var('versioncheck_force', false), true);
$info = explode("\n", $info);
$latest_version = trim($info[0]);
@@ -68,6 +63,7 @@ class acp_update
'S_UP_TO_DATE_AUTO' => $up_to_date_automatic,
'S_VERSION_CHECK' => true,
'U_ACTION' => $this->u_action,
+ 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'),
'LATEST_VERSION' => $latest_version,
'CURRENT_VERSION' => $config['version'],
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index e5f83faec3..1afec6183a 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -385,6 +385,31 @@ class acp_users
user_active_flip('flip', $user_id);
+ if ($user_row['user_type'] == USER_INACTIVE)
+ {
+ if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
+ {
+ include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
+
+ $messenger = new messenger(false);
+
+ $messenger->template('admin_welcome_activated', $user_row['user_lang']);
+
+ $messenger->to($user_row['user_email'], $user_row['username']);
+
+ $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']);
+ $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']);
+ $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']);
+ $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
+
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']))
+ );
+
+ $messenger->send(NOTIFY_EMAIL);
+ }
+ }
+
$message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
$log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
@@ -495,6 +520,56 @@ class acp_users
break;
+ case 'deloutbox':
+
+ if (confirm_box(true))
+ {
+ $msg_ids = array();
+ $lang = 'EMPTY';
+
+ $sql = 'SELECT msg_id
+ FROM ' . PRIVMSGS_TO_TABLE . "
+ WHERE author_id = $user_id
+ AND folder_id = " . PRIVMSGS_OUTBOX;
+ $result = $db->sql_query($sql);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ if (!function_exists('delete_pm'))
+ {
+ include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
+ }
+
+ do
+ {
+ $msg_ids[] = (int) $row['msg_id'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ $db->sql_freeresult($result);
+
+ delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX);
+
+ add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']);
+
+ $lang = 'EMPTIED';
+ }
+ $db->sql_freeresult($result);
+
+ trigger_error($user->lang['USER_OUTBOX_' . $lang] . adm_back_link($this->u_action . '&u=' . $user_id));
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'u' => $user_id,
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action,
+ 'update' => true))
+ );
+ }
+ break;
+
case 'moveposts':
if (!check_form_key($form_name))
@@ -650,6 +725,28 @@ class acp_users
trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&u=' . $user_id));
break;
+
+ case 'leave_nr':
+
+ if (confirm_box(true))
+ {
+ remove_newly_registered($user_id, $user_row);
+
+ add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']);
+ trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&u=' . $user_id));
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'u' => $user_id,
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action,
+ 'update' => true))
+ );
+ }
+
+ break;
}
// Handle registration info updates
@@ -775,7 +872,7 @@ class acp_users
{
$sql_ary += array(
'user_email' => $update_email,
- 'user_email_hash' => crc32($update_email) . strlen($update_email)
+ 'user_email_hash' => phpbb_email_hash($update_email),
);
add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email);
@@ -820,7 +917,11 @@ class acp_users
if ($user_id == $user->data['user_id'])
{
- $quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
+ $quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');
+ if ($user_row['user_new'])
+ {
+ $quick_tool_ary['leave_nr'] = 'LEAVE_NR';
+ }
}
else
{
@@ -836,12 +937,17 @@ class acp_users
$quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'));
}
- $quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
+ $quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');
if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE))
{
$quick_tool_ary['reactivate'] = 'FORCE';
}
+
+ if ($user_row['user_new'])
+ {
+ $quick_tool_ary['leave_nr'] = 'LEAVE_NR';
+ }
}
$s_action_options = '
';
@@ -1035,6 +1141,161 @@ class acp_users
break;
+ case 'warnings':
+ $user->add_lang('mcp');
+
+ // Set up general vars
+ $start = request_var('start', 0);
+ $deletemark = (isset($_POST['delmarked'])) ? true : false;
+ $deleteall = (isset($_POST['delall'])) ? true : false;
+ $confirm = (isset($_POST['confirm'])) ? true : false;
+ $marked = request_var('mark', array(0));
+ $message = utf8_normalize_nfc(request_var('message', '', true));
+
+ // Sort keys
+ $sort_days = request_var('st', 0);
+ $sort_key = request_var('sk', 't');
+ $sort_dir = request_var('sd', 'd');
+
+ // Delete entries if requested and able
+ if ($deletemark || $deleteall || $confirm)
+ {
+ if (confirm_box(true))
+ {
+ $where_sql = '';
+ $deletemark = request_var('delmarked', 0);
+ $deleteall = request_var('delall', 0);
+ if ($deletemark && $marked)
+ {
+ $sql_in = array();
+ foreach ($marked as $mark)
+ {
+ $sql_in[] = $mark;
+ }
+ $where_sql = ' AND ' . $db->sql_in_set('warning_id', $sql_in);
+ unset($sql_in);
+ }
+
+ if ($where_sql || $deleteall)
+ {
+ $sql = 'DELETE FROM ' . WARNINGS_TABLE . "
+ WHERE user_id = $user_id
+ $where_sql";
+ $db->sql_query($sql);
+
+ if ($deleteall)
+ {
+ $log_warnings = $deleted_warnings = 0;
+ }
+ else
+ {
+ $num_warnings = (int) $db->sql_affectedrows();
+ $deleted_warnings = ' user_warnings - ' . $num_warnings;
+ $log_warnings = ($num_warnings > 2) ? 2 : $num_warnings;
+ }
+
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_warnings = $deleted_warnings
+ WHERE user_id = $user_id";
+ $db->sql_query($sql);
+
+ switch ($log_warnings)
+ {
+ case 2:
+ add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings);
+ break;
+ case 1:
+ add_log('admin', 'LOG_WARNING_DELETED', $user_row['username']);
+ break;
+ default:
+ add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']);
+ break;
+ }
+ }
+ }
+ else
+ {
+ $s_hidden_fields = array(
+ 'i' => $id,
+ 'mode' => $mode,
+ 'u' => $user_id,
+ 'mark' => $marked,
+ );
+ if (isset($_POST['delmarked']))
+ {
+ $s_hidden_fields['delmarked'] = 1;
+ }
+ if (isset($_POST['delall']))
+ {
+ $s_hidden_fields['delall'] = 1;
+ }
+ if (isset($_POST['delall']) || (isset($_POST['delmarked']) && sizeof($marked)))
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
+ }
+ }
+ }
+
+ $sql = 'SELECT w.warning_id, w.warning_time, w.post_id, l.log_operation, l.log_data, l.user_id AS mod_user_id, m.username AS mod_username, m.user_colour AS mod_user_colour
+ FROM ' . WARNINGS_TABLE . ' w
+ LEFT JOIN ' . LOG_TABLE . ' l
+ ON (w.log_id = l.log_id)
+ LEFT JOIN ' . USERS_TABLE . ' m
+ ON (l.user_id = m.user_id)
+ WHERE w.user_id = ' . $user_id . '
+ ORDER BY w.warning_time DESC';
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ if (!$row['log_operation'])
+ {
+ // We do not have a log-entry anymore, so there is no data available
+ $row['action'] = $user->lang['USER_WARNING_LOG_DELETED'];
+ }
+ else
+ {
+ $row['action'] = (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}';
+ if (!empty($row['log_data']))
+ {
+ $log_data_ary = @unserialize($row['log_data']);
+ $log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary;
+
+ if (isset($user->lang[$row['log_operation']]))
+ {
+ // Check if there are more occurrences of % than arguments, if there are we fill out the arguments array
+ // It doesn't matter if we add more arguments than placeholders
+ if ((substr_count($row['action'], '%') - sizeof($log_data_ary)) > 0)
+ {
+ $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($row['action'], '%') - sizeof($log_data_ary), ''));
+ }
+ $row['action'] = vsprintf($row['action'], $log_data_ary);
+ $row['action'] = bbcode_nl2br(censor_text($row['action']));
+ }
+ else if (!empty($log_data_ary))
+ {
+ $row['action'] .= '
' . implode('', $log_data_ary);
+ }
+ }
+ }
+
+
+ $template->assign_block_vars('warn', array(
+ 'ID' => $row['warning_id'],
+ 'USERNAME' => ($row['log_operation']) ? get_username_string('full', $row['mod_user_id'], $row['mod_username'], $row['mod_user_colour']) : '-',
+ 'ACTION' => make_clickable($row['action']),
+ 'DATE' => $user->format_date($row['warning_time']),
+ ));
+ }
+ $db->sql_freeresult($result);
+
+ $template->assign_vars(array(
+ 'S_WARNINGS' => true,
+ 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'),
+ ));
+
+ break;
+
case 'profile':
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
@@ -1136,54 +1397,7 @@ class acp_users
$db->sql_query($sql);
// Update Custom Fields
- if (sizeof($cp_data))
- {
- switch ($db->sql_layer)
- {
- case 'oracle':
- case 'firebird':
- case 'postgres':
- $right_delim = $left_delim = '"';
- break;
-
- case 'sqlite':
- case 'mssql':
- case 'mssql_odbc':
- $right_delim = ']';
- $left_delim = '[';
- break;
-
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $right_delim = $left_delim = '`';
- break;
- }
-
- foreach ($cp_data as $key => $value)
- {
- // Firebird is case sensitive with delimiter
- $cp_data[$left_delim . (($db->sql_layer == 'firebird') ? strtoupper($key) : $key) . $right_delim] = $value;
- unset($cp_data[$key]);
- }
-
- $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . '
- SET ' . $db->sql_build_array('UPDATE', $cp_data) . "
- WHERE user_id = $user_id";
- $db->sql_query($sql);
-
- if (!$db->sql_affectedrows())
- {
- $cp_data['user_id'] = (int) $user_id;
-
- $db->sql_return_on_error(true);
-
- $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data);
- $db->sql_query($sql);
-
- $db->sql_return_on_error(false);
- }
- }
+ $cp->update_profile_field_data($user_id, $cp_data);
trigger_error($user->lang['USER_PROFILE_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id));
}
@@ -1476,8 +1690,19 @@ class acp_users
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
+ if (!$config['allow_avatar'] && $user_row['user_avatar_type'])
+ {
+ $error[] = $user->lang['USER_AVATAR_NOT_ALLOWED'];
+ }
+ else if ((($user_row['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) ||
+ (($user_row['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) ||
+ (($user_row['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local']))
+ {
+ $error[] = $user->lang['USER_AVATAR_TYPE_NOT_ALLOWED'];
+ }
+
// Generate users avatar
- $avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']) : '

';
+ $avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height'], 'USER_AVATAR', true) : '

';
$display_gallery = (isset($_POST['display_gallery'])) ? true : false;
$avatar_select = basename(request_var('avatar_select', ''));
@@ -1490,10 +1715,11 @@ class acp_users
$template->assign_vars(array(
'S_AVATAR' => true,
- 'S_CAN_UPLOAD' => ($can_upload && $config['allow_avatar_upload']) ? true : false,
- 'S_ALLOW_REMOTE' => ($config['allow_avatar_remote']) ? true : false,
- 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false,
- 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false,
+ 'S_UPLOAD_FILE' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_upload']) ? true : false,
+ 'S_REMOTE_UPLOAD' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_remote_upload']) ? true : false,
+ 'S_ALLOW_REMOTE' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false,
+ 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false,
+ 'S_IN_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery) ? true : false,
'AVATAR_IMAGE' => $avatar_img,
'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'],
@@ -1551,9 +1777,9 @@ class acp_users
include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx);
- $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', !$user->optionget('bbcode'))) ? false : true) : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', !$user->optionget('smilies'))) ? false : true) : false;
- $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false;
+ $enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false;
$signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true));
$preview = (isset($_POST['preview'])) ? true : false;
@@ -1562,6 +1788,10 @@ class acp_users
{
include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false;
+ $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
+
$message_parser = new parse_message($signature);
// Allowing Quote BBCode
@@ -1579,8 +1809,13 @@ class acp_users
if (!sizeof($error) && $submit)
{
+ $this->optionset($user_row, 'sig_bbcode', $enable_bbcode);
+ $this->optionset($user_row, 'sig_smilies', $enable_smilies);
+ $this->optionset($user_row, 'sig_links', $enable_urls);
+
$sql_ary = array(
'user_sig' => (string) $message_parser->message,
+ 'user_options' => $user_row['user_options'],
'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield
);
@@ -1871,6 +2106,29 @@ class acp_users
}
break;
+
+ case 'approve':
+
+ if (confirm_box(true))
+ {
+ if (!$group_id)
+ {
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
+ }
+ group_user_attributes($action, $group_id, $user_id);
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'u' => $user_id,
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action,
+ 'g' => $group_id))
+ );
+ }
+
+ break;
}
// Add user to group?
@@ -1963,10 +2221,12 @@ class acp_users
'U_DEFAULT' => $this->u_action . "&action=default&u=$user_id&g=" . $data['group_id'],
'U_DEMOTE_PROMOTE' => $this->u_action . '&action=' . (($data['group_leader']) ? 'demote' : 'promote') . "&u=$user_id&g=" . $data['group_id'],
'U_DELETE' => $this->u_action . "&action=delete&u=$user_id&g=" . $data['group_id'],
+ 'U_APPROVE' => ($group_type == 'pending') ? $this->u_action . "&action=approve&u=$user_id&g=" . $data['group_id'] : '',
'GROUP_NAME' => ($group_type == 'special') ? $user->lang['G_' . $data['group_name']] : $data['group_name'],
'L_DEMOTE_PROMOTE' => ($data['group_leader']) ? $user->lang['GROUP_DEMOTE'] : $user->lang['GROUP_PROMOTE'],
+ 'S_IS_MEMBER' => ($group_type != 'pending') ? true : false,
'S_NO_DEFAULT' => ($user_row['group_id'] != $data['group_id']) ? true : false,
'S_SPECIAL_GROUP' => ($group_type == 'special') ? true : false,
)
diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php
index 596c2fc743..1cb9545967 100644
--- a/phpBB/includes/acp/acp_words.php
+++ b/phpBB/includes/acp/acp_words.php
@@ -23,7 +23,7 @@ if (!defined('IN_PHPBB'))
class acp_words
{
var $u_action;
-
+
function main($id, $mode)
{
global $db, $user, $auth, $template, $cache;
@@ -47,8 +47,9 @@ class acp_words
switch ($action)
{
case 'edit':
+
$word_id = request_var('id', 0);
-
+
if (!$word_id)
{
trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
@@ -73,7 +74,7 @@ class acp_words
'REPLACEMENT' => (isset($word_info['replacement'])) ? $word_info['replacement'] : '',
'S_HIDDEN_FIELDS' => $s_hidden_fields)
);
-
+
return;
break;
@@ -84,11 +85,12 @@ class acp_words
{
trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING);
}
+
$word_id = request_var('id', 0);
$word = utf8_normalize_nfc(request_var('word', '', true));
$replacement = utf8_normalize_nfc(request_var('replacement', '', true));
-
- if (!$word || !$replacement)
+
+ if ($word === '' || $replacement === '')
{
trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
}
diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php
index 72d86676a6..58b650650c 100644
--- a/phpBB/includes/acp/info/acp_board.php
+++ b/phpBB/includes/acp/info/acp_board.php
@@ -26,6 +26,7 @@ class acp_board_info
'message' => array('title' => 'ACP_MESSAGE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_MESSAGES')),
'post' => array('title' => 'ACP_POST_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'signature' => array('title' => 'ACP_SIGNATURE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
+ 'feed' => array('title' => 'ACP_FEED_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'registration' => array('title' => 'ACP_REGISTER_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
'auth' => array('title' => 'ACP_AUTH_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')),
diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php
index 22de666af3..6f341742f3 100644
--- a/phpBB/includes/acp/info/acp_permissions.php
+++ b/phpBB/includes/acp/info/acp_permissions.php
@@ -24,6 +24,7 @@ class acp_permissions_info
'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')),
'setting_forum_local' => array('title' => 'ACP_FORUM_PERMISSIONS', 'auth' => 'acl_a_fauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
+ 'setting_forum_copy' => array('title' => 'ACP_FORUM_PERMISSIONS_COPY', 'auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
'setting_mod_local' => array('title' => 'ACP_FORUM_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')),
'setting_user_global' => array('title' => 'ACP_USERS_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_CAT_USERS')),
'setting_user_local' => array('title' => 'ACP_USERS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_CAT_USERS')),
diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php
new file mode 100644
index 0000000000..de5dcdb8ad
--- /dev/null
+++ b/phpBB/includes/acp/info/acp_send_statistics.php
@@ -0,0 +1,37 @@
+ 'acp_send_statistics',
+ 'title' => 'ACP_SEND_STATISTICS',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php
index 0cd5f7ae97..10081ac870 100644
--- a/phpBB/includes/acp/info/acp_users.php
+++ b/phpBB/includes/acp/info/acp_users.php
@@ -22,6 +22,7 @@ class acp_users_info
'modes' => array(
'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
+ 'warnings' => array('title' => 'ACP_USER_WARNINGS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'profile' => array('title' => 'ACP_USER_PROFILE', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'prefs' => array('title' => 'ACP_USER_PREFS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
'avatar' => array('title' => 'ACP_USER_AVATAR', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')),
diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php
index 1196a9a0f0..02819f9e78 100644
--- a/phpBB/includes/auth.php
+++ b/phpBB/includes/auth.php
@@ -64,9 +64,9 @@ class auth
$db->sql_freeresult($result);
$cache->put('_acl_options', $this->acl_options);
- $this->acl_cache($userdata);
}
- else if (!trim($userdata['user_permissions']))
+
+ if (!trim($userdata['user_permissions']))
{
$this->acl_cache($userdata);
}
@@ -608,22 +608,26 @@ class auth
// Now grab group settings - non-role specific...
$sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . '
- FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug' . $sql_opts_from . '
+ FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g' . $sql_opts_from . '
WHERE a.auth_role_id = 0 ' .
(($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . '
AND a.group_id = ug.group_id
+ AND g.group_id = ug.group_id
AND ug.user_pending = 0
+ AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
$sql_forum
$sql_opts";
// Now grab group settings - role specific...
$sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . '
- FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
+ FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . '
WHERE a.auth_role_id = r.role_id ' .
(($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . '
AND a.group_id = ug.group_id
+ AND g.group_id = ug.group_id
AND ug.user_pending = 0
+ AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
' . (($sql_user) ? 'AND ug.' . $sql_user : '') . "
$sql_forum
$sql_opts";
@@ -825,9 +829,11 @@ class auth
// Now grab group-specific permission settings
$sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting
- FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug
+ FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g
WHERE a.group_id = ug.group_id
+ AND g.group_id = ug.group_id
AND ug.user_pending = 0
+ AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
AND ug.user_id = ' . $user_id;
$result = $db->sql_query($sql);
diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php
index 930f5a0632..391e7abb0e 100644
--- a/phpBB/includes/auth/auth_apache.php
+++ b/phpBB/includes/auth/auth_apache.php
@@ -217,6 +217,7 @@ function user_row_apache($username, $password)
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
'user_ip' => $user->ip,
+ 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
);
}
diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php
index 24d4c56614..5dc141ff77 100644
--- a/phpBB/includes/auth/auth_db.php
+++ b/phpBB/includes/auth/auth_db.php
@@ -68,7 +68,6 @@ function login_db(&$username, &$password)
if ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts'])
{
$confirm_id = request_var('confirm_id', '');
- $confirm_code = request_var('confirm_code', '');
// Visual Confirmation handling
if (!$confirm_id)
@@ -81,41 +80,15 @@ function login_db(&$username, &$password)
}
else
{
- global $user;
+ $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $captcha->init(CONFIRM_LOGIN);
+ $vc_response = $captcha->validate();
- $sql = 'SELECT code
- FROM ' . CONFIRM_TABLE . "
- WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_LOGIN;
- $result = $db->sql_query($sql);
- $confirm_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($confirm_row)
- {
- if (strcasecmp($confirm_row['code'], $confirm_code) === 0)
- {
- $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
- WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_LOGIN;
- $db->sql_query($sql);
- }
- else
- {
- return array(
- 'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'CONFIRM_CODE_WRONG',
- 'user_row' => $row,
- );
- }
- }
- else
+ if ($vc_response)
{
return array(
'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'CONFIRM_CODE_WRONG',
+ 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
'user_row' => $row,
);
}
@@ -157,7 +130,7 @@ function login_db(&$username, &$password)
$row['user_pass_convert'] = 0;
$row['user_password'] = $hash;
}
- else
+ else
{
// Although we weren't able to convert this password we have to
// increase login attempt count to make sure this cannot be exploited
diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php
index d49662fb2d..a6092baba5 100644
--- a/phpBB/includes/auth/auth_ldap.php
+++ b/phpBB/includes/auth/auth_ldap.php
@@ -63,9 +63,11 @@ function init_ldap()
// ldap_connect only checks whether the specified server is valid, so the connection might still fail
$search = @ldap_search(
$ldap,
- $config['ldap_base_dn'],
+ htmlspecialchars_decode($config['ldap_base_dn']),
ldap_user_filter($user->data['username']),
- (empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
+ (empty($config['ldap_email'])) ?
+ array(htmlspecialchars_decode($config['ldap_uid'])) :
+ array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
0,
1
);
@@ -85,7 +87,7 @@ function init_ldap()
return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']);
}
- if (!empty($config['ldap_email']) && !isset($result[0][$config['ldap_email']]))
+ if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])]))
{
return $user->lang['LDAP_NO_EMAIL'];
}
@@ -152,7 +154,7 @@ function login_ldap(&$username, &$password)
if ($config['ldap_user'] || $config['ldap_password'])
{
- if (!@ldap_bind($ldap, $config['ldap_user'], htmlspecialchars_decode($config['ldap_password'])))
+ if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
{
return $user->lang['LDAP_NO_SERVER_CONNECTION'];
}
@@ -160,9 +162,11 @@ function login_ldap(&$username, &$password)
$search = @ldap_search(
$ldap,
- $config['ldap_base_dn'],
+ htmlspecialchars_decode($config['ldap_base_dn']),
ldap_user_filter($username),
- (empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
+ (empty($config['ldap_email'])) ?
+ array(htmlspecialchars_decode($config['ldap_uid'])) :
+ array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
0,
1
);
@@ -223,10 +227,11 @@ function login_ldap(&$username, &$password)
$ldap_user_row = array(
'username' => $username,
'user_password' => phpbb_hash($password),
- 'user_email' => (!empty($config['ldap_email'])) ? $ldap_result[0][$config['ldap_email']][0] : '',
+ 'user_email' => (!empty($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
'user_ip' => $user->ip,
+ 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
);
unset($ldap_result);
@@ -276,7 +281,8 @@ function ldap_user_filter($username)
$filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')';
if ($config['ldap_user_filter'])
{
- $filter = "(&$filter({$config['ldap_user_filter']}))";
+ $_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})";
+ $filter = "(&{$filter}{$_filter})";
}
return $filter;
}
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index 562488db70..693523dcbb 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -265,7 +265,7 @@ class bbcode
case 6:
$this->bbcode_cache[$bbcode_id] = array(
'preg' => array(
- '!\[color=(#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
+ '!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
)
);
break;
diff --git a/phpBB/includes/cache.php b/phpBB/includes/cache.php
index fc9a01ae4e..1effada666 100644
--- a/phpBB/includes/cache.php
+++ b/phpBB/includes/cache.php
@@ -84,7 +84,15 @@ class cache extends acm
$censors = array();
while ($row = $db->sql_fetchrow($result))
{
- $censors['match'][] = '#(?=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false)
+ {
+ $censors['match'][] = '#(?sql_freeresult($result);
diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php
new file mode 100644
index 0000000000..73406a954f
--- /dev/null
+++ b/phpBB/includes/captcha/captcha_factory.php
@@ -0,0 +1,100 @@
+ array(),
+ 'unavailable' => array(),
+ );
+
+ $dp = @opendir($phpbb_root_path . 'includes/captcha/plugins');
+
+ if ($dp)
+ {
+ while (($file = readdir($dp)) !== false)
+ {
+ if ((preg_match('#_plugin\.' . $phpEx . '$#', $file)))
+ {
+ $name = preg_replace('#^(.*?)_plugin\.' . $phpEx . '$#', '\1', $file);
+ if (!class_exists($name))
+ {
+ include($phpbb_root_path . "includes/captcha/plugins/$file");
+ }
+
+ if (call_user_func(array($name, 'is_available')))
+ {
+ $captchas['available'][$name] = call_user_func(array($name, 'get_name'));
+ }
+ else
+ {
+ $captchas['unavailable'][$name] = call_user_func(array($name, 'get_name'));
+ }
+ }
+ }
+ closedir($dp);
+ }
+
+ return $captchas;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php
index 9734a63c1b..96e39af85b 100644
--- a/phpBB/includes/captcha/captcha_gd.php
+++ b/phpBB/includes/captcha/captcha_gd.php
@@ -34,8 +34,8 @@ class captcha
function execute($code, $seed)
{
global $config;
- srand($seed);
- //mt_srand($seed);
+
+ mt_srand($seed);
// Create image
$img = imagecreatetruecolor($this->width, $this->height);
@@ -108,7 +108,7 @@ class captcha
if ($config['captcha_gd_3d_noise'])
{
- $xoffset = rand(0,9);
+ $xoffset = mt_rand(0,9);
$noise_bitmaps = $this->captcha_noise_bg_bitmaps();
for ($i = 0; $i < $code_len; ++$i)
{
diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/includes/captcha/captcha_gd_wave.php
new file mode 100644
index 0000000000..f706c98d43
--- /dev/null
+++ b/phpBB/includes/captcha/captcha_gd_wave.php
@@ -0,0 +1,845 @@
+width;
+ $img_y = $this->height;
+
+ // Generate image
+ $img = imagecreatetruecolor($img_x, $img_y);
+ $x_grid = mt_rand(6, 10);
+ $y_grid = mt_rand(6, 10);
+
+ // Ok, so lets cut to the chase. We could accurately represent this in 3d and
+ // do all the appropriate linear transforms. my questions is... why bother?
+ // The computational overhead is unnecessary when you consider the simple fact:
+ // we're not here to accurately represent a model, but to just show off some random-ish
+ // polygons
+
+ // Conceive of 3 spaces.
+ // 1) planar-space (discrete "pixel" grid)
+ // 2) 3-space. (planar-space with z/height aspect)
+ // 3) image space (pixels on the screen)
+ // resolution of the planar-space we're embedding the text code in
+ $plane_x = 100;
+ $plane_y = 30;
+
+ $subdivision_factor = 3;
+
+ // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space
+ $box = array(
+ 'upper_left' => array(
+ 'x' => mt_rand(5, 15),
+ 'y' => mt_rand(10, 15)
+ ),
+ 'upper_right' => array(
+ 'x' => mt_rand($img_x - 35, $img_x - 19),
+ 'y' => mt_rand(10, 17)
+ ),
+ 'lower_left' => array(
+ 'x' => mt_rand($img_x - 5, $img_x - 45),
+ 'y' => mt_rand($img_y - 0, $img_y - 15)
+ ),
+ );
+
+ $box['lower_right'] = array(
+ 'x' => $box['lower_left']['x'] + $box['upper_left']['x'] - $box['upper_right']['x'],
+ 'y' => $box['lower_left']['y'] + $box['upper_left']['y'] - $box['upper_right']['y'],
+ );
+
+ // TODO
+ $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));
+ imagefill($img, 0, 0, $background);
+ $black = imagecolorallocate($img, 0, 0, 0);
+
+ $random = array();
+ $fontcolors = array();
+
+ for ($i = 0; $i < 15; ++$i)
+ {
+ $random[$i] = imagecolorallocate($img, mt_rand(120, 255), mt_rand(120, 255), mt_rand(120, 255));
+ }
+
+ $fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
+
+ $colors = array();
+
+ $minr = mt_rand(20, 30);
+ $ming = mt_rand(20, 30);
+ $minb = mt_rand(20, 30);
+
+ $maxr = mt_rand(150, 230);
+ $maxg = mt_rand(150, 230);
+ $maxb = mt_rand(150, 230);
+
+ for ($i = -30; $i <= 30; ++$i)
+ {
+ $coeff1 = ($i + 12) / 45;
+ $coeff2 = 1 - $coeff1;
+ $colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb));
+ }
+
+ // $img_buffer is the last row of 3-space positions (converted to img-space), cached
+ // (using this means we don't need to recalculate all 4 positions for each new polygon,
+ // merely the newest point that we're adding, which is then cached.
+ $img_buffer = array(array(), array());
+
+ // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space
+ $dxx = ($box['upper_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_x);
+ $dxy = ($box['upper_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_x);
+
+ // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space
+ $dyx = ($box['lower_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_y);
+ $dyy = ($box['lower_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_y);
+
+ // Initial captcha-letter offset in planar-space
+ $plane_offset_x = mt_rand(3, 8);
+ $plane_offset_y = mt_rand( 12, 15);
+
+ // character map
+ $map = $this->captcha_bitmaps();
+
+ // matrix
+ $plane = array();
+
+ // for each character, we'll silkscreen it into our boolean pixel plane
+ for ($c = 0, $code_num = strlen($code); $c < $code_num; ++$c)
+ {
+ $letter = $code[$c];
+
+ for ($x = $map['width'] - 1; $x >= 0; --$x)
+ {
+ for ($y = $map['height'] - 1; $y >= 0; --$y)
+ {
+ if ($map['data'][$letter][$y][$x])
+ {
+ $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true;
+ }
+ }
+ }
+ $plane_offset_x += 11;
+ }
+
+ // calculate our first buffer, we can't actually draw polys with these yet
+ // img_pos_prev == screen x,y location to our immediate left.
+ // img_pos_cur == current screen x,y location
+ // we calculate screen position of our
+ // current cell based on the difference from the previous cell
+ // rather than recalculating from absolute coordinates
+ // What we cache into the $img_buffer contains the raised text coordinates.
+ $img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']);
+ $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor);
+ $full_x = $plane_x * $subdivision_factor;
+ $full_y = $plane_y * $subdivision_factor;
+
+ for ($x = 1; $x <= $full_x; ++$x)
+ {
+ $cur_height = $this->wave_height($x, 0, $subdivision_factor);
+ $offset = $cur_height - $prev_height;
+ $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
+
+ $img_buffer[0][$x] = $img_pos_cur;
+ $img_pos_prev = $img_pos_cur;
+ $prev_height = $cur_height;
+ }
+
+ for ($y = 1; $y <= $full_y; ++$y)
+ {
+ // swap buffers
+ $buffer_cur = $y & 1;
+ $buffer_prev = 1 - $buffer_cur;
+
+ $prev_height = $this->wave_height(0, $y, $subdivision_factor);
+ $offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor);
+ $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, min($img_buffer[$buffer_prev][0][1] + $dyy + $offset, $img_y - 1));
+
+ // make sure we don't try to write off the page
+ $img_pos_prev = $img_pos_cur;
+
+ $img_buffer[$buffer_cur][0] = $img_pos_cur;
+
+ for ($x = 1; $x <= $full_x; ++$x)
+ {
+ $cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, 1, $x_grid, $y_grid);
+
+ // height is a z-factor, not a y-factor
+ $offset = $cur_height - $prev_height;
+ $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
+
+ // height is float, index it to an int, get closest color
+ $color = $colors[intval($cur_height)];
+ $img_pos_prev = $img_pos_cur;
+ $prev_height = $cur_height;
+
+ $y_index_old = intval(($y - 1) / $subdivision_factor);
+ $y_index_new = intval($y / $subdivision_factor);
+ $x_index_old = intval(($x - 1) / $subdivision_factor);
+ $x_index_new = intval($x / $subdivision_factor);
+
+ if (!empty($plane[$y_index_new][$x_index_new]))
+ {
+ $img_pos_cur[1] += $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height;
+ $color = $colors[20];
+ }
+ $img_pos_cur[1] = min($img_pos_cur[1], $img_y - 1);
+ $img_buffer[$buffer_cur][$x] = $img_pos_cur;
+
+ // Smooth the edges as much as possible by having not more than one low<->high traingle per square
+ // Otherwise, just
+ $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new]));
+ $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old]));
+
+ // natural switching
+ $mode = ($x + $y) & 1;
+
+ // override if it requires it
+ if ($diag_down != $diag_up)
+ {
+ $mode = $diag_up;
+ }
+
+ if ($mode)
+ {
+ // +-/ /
+ // 1 |/ 2 /|
+ // / /-+
+ $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]);
+ $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]);
+ }
+ else
+ {
+ // \ \-+
+ // 1 |\ 2 \|
+ // +-\ \
+ $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]);
+ $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]);
+ }
+
+ imagefilledpolygon($img, $poly1, 3, $color);
+ imagefilledpolygon($img, $poly2, 3, $color);
+ }
+ }
+
+ // Output image
+ header('Content-Type: image/png');
+ header('Cache-control: no-cache, no-store');
+ //$mtime = explode(' ', microtime());
+ //$totaltime = $mtime[0] + $mtime[1] - $starttime;
+
+ //echo $totaltime . "
\n";
+ //echo memory_get_usage() - $tmp;
+ imagepng($img);
+ imagedestroy($img);
+ }
+
+ function wave_height($x, $y, $factor = 1, $tweak = 0.7)
+ {
+ // stretch the wave. TODO: pretty it up
+ $x = $x/5 + 180;
+ $y = $y/4;
+ return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak);
+ }
+
+ function grid_height($x, $y, $factor = 1, $x_grid, $y_grid)
+ {
+ return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0);
+ }
+
+ function captcha_bitmaps()
+ {
+ return array(
+ 'width' => 9,
+ 'height' => 13,
+ 'data' => array(
+ 'A' => array(
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'B' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'C' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'D' => array(
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'E' => array(
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'F' => array(
+ array(0,0,1,1,1,1,1,1,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'G' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'H' => array(
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'I' => array(
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'J' => array(
+ array(0,0,0,0,0,0,1,1,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'K' => array(
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,1,0,0,0,0,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'L' => array(
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'M' => array(
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,1,0,0,0,1,1,0),
+ array(0,1,0,1,0,1,0,1,0),
+ array(0,1,0,0,1,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'N' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,1,0,0,0,0,0,0,1),
+ array(1,0,1,0,0,0,0,0,1),
+ array(1,0,0,1,0,0,0,0,1),
+ array(1,0,0,0,1,0,0,0,1),
+ array(1,0,0,0,0,1,0,0,1),
+ array(1,0,0,0,0,0,1,0,1),
+ array(1,0,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'O' => array(
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'P' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Q' => array(
+ array(0,0,1,1,1,1,0,0,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,1,0,0,1,0),
+ array(1,0,0,0,0,1,0,1,0),
+ array(0,1,0,0,0,0,1,0,0),
+ array(0,0,1,1,1,1,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'R' => array(
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(1,1,1,1,1,1,0,0,0),
+ array(1,0,1,0,0,0,0,0,0),
+ array(1,0,0,1,0,0,0,0,0),
+ array(1,0,0,0,1,0,0,0,0),
+ array(1,0,0,0,0,1,0,0,0),
+ array(1,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'S' => array(
+ array(0,0,1,1,1,1,1,1,1),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(1,1,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'T' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'U' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'V' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'W' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,1,0,0,0,1),
+ array(1,0,0,1,0,1,0,0,1),
+ array(1,0,1,0,0,0,1,0,1),
+ array(1,1,0,0,0,0,0,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'X' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Y' => array(
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,0,0,1,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ 'Z' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,0,0,0,0),
+ array(0,0,1,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '1' => array(
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,1,0,0,0,0),
+ array(0,0,1,0,1,0,0,0,0),
+ array(0,1,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '2' => array(
+ array(0,0,0,1,1,1,0,0,0),
+ array(0,0,1,0,0,0,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,1,0,0,0,0,0),
+ array(0,0,1,0,0,0,0,0,0),
+ array(0,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '3' => array(
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '4' => array(
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,1,0),
+ array(0,0,0,0,0,1,0,1,0),
+ array(0,0,0,0,1,0,0,1,0),
+ array(0,0,0,1,0,0,0,1,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,1,1,1,1,1,1,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '5' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(0,1,0,0,0,0,0,0,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '6' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,0,0,0,0,0,0),
+ array(1,0,0,1,1,1,1,0,0),
+ array(1,0,1,0,0,0,0,1,0),
+ array(1,1,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '7' => array(
+ array(1,1,1,1,1,1,1,1,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,1,0),
+ array(0,0,0,0,0,0,1,0,0),
+ array(0,0,0,0,0,1,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,1,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '8' => array(
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,1,0,0,0,0,0,1,0),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(1,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,0),
+ array(0,0,1,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ '9' => array(
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,1,1),
+ array(0,0,1,1,1,1,1,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,0,0,0,0,0,0,0,1),
+ array(0,1,0,0,0,0,0,0,1),
+ array(0,0,1,0,0,0,0,1,0),
+ array(0,0,0,1,1,1,1,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ array(0,0,0,0,0,0,0,0,0),
+ ),
+ )
+ );
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php
new file mode 100644
index 0000000000..db4b7649c7
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/captcha_abstract.php
@@ -0,0 +1,375 @@
+confirm_id = request_var('confirm_id', '');
+ $this->confirm_code = request_var('confirm_code', '');
+ $refresh = request_var('refresh_vc', false) && $config['confirm_refresh'];
+
+ $this->type = (int) $type;
+
+ if (!strlen($this->confirm_id) || !$this->load_code())
+ {
+ // we have no confirm ID, better get ready to display something
+ $this->generate_code();
+ }
+ else if ($refresh)
+ {
+ $this->regenerate_code();
+ }
+ }
+
+ function execute_demo()
+ {
+ global $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $captcha = new captcha();
+ define('IMAGE_OUTPUT', 1);
+ $captcha->execute($this->code, $this->seed);
+ }
+
+ function execute()
+ {
+ if (empty($this->code))
+ {
+ if (!$this->load_code())
+ {
+ // invalid request, bail out
+ return false;
+ }
+ }
+ $captcha = new captcha();
+ define('IMAGE_OUTPUT', 1);
+ $captcha->execute($this->code, $this->seed);
+ }
+
+ function get_template()
+ {
+ global $config, $user, $template, $phpEx, $phpbb_root_path;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type);
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '
', '');
+
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE_LINK' => $link,
+ 'CONFIRM_IMAGE' => '

',
+ 'CONFIRM_IMG' => '

',
+ 'CONFIRM_ID' => $this->confirm_id,
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false,
+ 'L_CONFIRM_EXPLAIN' => $explain,
+ ));
+
+ return 'captcha_default.html';
+ }
+ }
+
+ function get_demo_template($id)
+ {
+ global $config, $user, $template, $phpbb_admin_path, $phpEx;
+
+ $variables = '';
+
+ if (is_array($this->captcha_vars))
+ {
+ foreach ($this->captcha_vars as $captcha_var => $template_var)
+ {
+ $variables .= '&' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]);
+ }
+ }
+
+ // acp_captcha has a delivery function; let's use it
+ $template->assign_vars(array(
+ 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()) . $variables,
+ 'CONFIRM_ID' => $this->confirm_id,
+ ));
+
+ return 'captcha_default_acp_demo.html';
+ }
+
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required for posting.php - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['confirm_code'] = $this->confirm_code;
+ }
+ $hidden_fields['confirm_id'] = $this->confirm_id;
+ return $hidden_fields;
+ }
+
+ function garbage_collect($type)
+ {
+ global $db, $config;
+
+ $sql = 'SELECT DISTINCT c.session_id
+ FROM ' . CONFIRM_TABLE . ' c
+ LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
+ WHERE s.session_id IS NULL' .
+ ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
+ $result = $db->sql_query($sql);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $sql_in = array();
+ do
+ {
+ $sql_in[] = (string) $row['session_id'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ if (sizeof($sql_in))
+ {
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
+ WHERE ' . $db->sql_in_set('session_id', $sql_in);
+ $db->sql_query($sql);
+ }
+ }
+ $db->sql_freeresult($result);
+ }
+
+ function uninstall()
+ {
+ $this->garbage_collect(0);
+ }
+
+ function install()
+ {
+ return;
+ }
+
+ function validate()
+ {
+ global $config, $db, $user;
+
+ $error = '';
+ if (!$this->confirm_id)
+ {
+ $error = $user->lang['CONFIRM_CODE_WRONG'];
+ }
+ else
+ {
+ if ($this->check_code())
+ {
+ // $this->delete_code(); commented out to allow posting.php to repeat the question
+ $this->solved = true;
+ }
+ else
+ {
+ $error = $user->lang['CONFIRM_CODE_WRONG'];
+ }
+ }
+
+ if (strlen($error))
+ {
+ // okay, incorrect answer. Let's ask a new question.
+ $this->new_attempt();
+ return $error;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * The old way to generate code, suitable for GD and non-GD. Resets the internal state.
+ */
+ function generate_code()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->confirm_id = md5(unique_id($user->ip));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'confirm_id' => (string) $this->confirm_id,
+ 'session_id' => (string) $user->session_id,
+ 'confirm_type' => (int) $this->type,
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)
+ );
+ $db->sql_query($sql);
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function regenerate_code()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)) . '
+ WHERE
+ confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
+ AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
+ $db->sql_query($sql);
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function new_attempt()
+ {
+ global $db, $user;
+
+ $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->seed = hexdec(substr(unique_id(), 4, 10));
+ $this->solved = 0;
+ // compute $seed % 0x7fffffff
+ $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff);
+
+ $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
+ 'code' => (string) $this->code,
+ 'seed' => (int) $this->seed)) . '
+ , attempts = attempts + 1
+ WHERE
+ confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\'
+ AND session_id = \'' . $db->sql_escape($user->session_id) . '\'';
+ $db->sql_query($sql);
+ }
+
+ /**
+ * Look up everything we need for painting&checking.
+ */
+ function load_code()
+ {
+ global $db, $user;
+
+ $sql = 'SELECT code, seed, attempts
+ FROM ' . CONFIRM_TABLE . "
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $this->code = $row['code'];
+ $this->seed = $row['seed'];
+ $this->attempts = $row['attempts'];
+ return true;
+ }
+
+ return false;
+ }
+
+ function check_code()
+ {
+ return (strcasecmp($this->code, $this->confirm_code) === 0);
+ }
+
+ function delete_code()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
+ WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $db->sql_query($sql);
+ }
+
+ function get_attempt_count()
+ {
+ return $this->attempts;
+ }
+
+ function reset()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
+ WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . (int) $this->type;
+ $db->sql_query($sql);
+
+ // we leave the class usable by generating a new question
+ $this->generate_code();
+ }
+
+ function is_solved()
+ {
+ if (request_var('confirm_code', false) && $this->solved === 0)
+ {
+ $this->validate();
+ }
+ return (bool) $this->solved;
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return false;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php
new file mode 100644
index 0000000000..a85566deff
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php
@@ -0,0 +1,163 @@
+ 'CAPTCHA_GD_X_GRID',
+ 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID',
+ 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE',
+// 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED',
+ 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE',
+ 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE',
+ 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS',
+ );
+
+ function phpbb_captcha_gd()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (!class_exists('captcha'))
+ {
+ include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
+ }
+ }
+
+ function &get_instance()
+ {
+ $instance =& new phpbb_captcha_gd();
+ return $instance;
+ }
+
+ function is_available()
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (@extension_loaded('gd'))
+ {
+ return true;
+ }
+
+ if (!function_exists('can_load_dll'))
+ {
+ include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
+ }
+
+ return can_load_dll('gd');
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_GD';
+ }
+
+ function get_class_name()
+ {
+ return 'phpbb_captcha_gd';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $db, $user, $auth, $template;
+ global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+
+ $user->add_lang('acp/board');
+
+ $config_vars = array(
+ 'enable_confirm' => 'REG_ENABLE',
+ 'enable_post_confirm' => 'POST_ENABLE',
+ 'confirm_refresh' => 'CONFIRM_REFRESH',
+ 'captcha_gd' => 'CAPTCHA_GD',
+ );
+
+ $module->tpl_name = 'captcha_gd_acp';
+ $module->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('submit', '');
+
+ if ($submit && check_form_key($form_key))
+ {
+ $captcha_vars = array_keys($this->captcha_vars);
+ foreach ($captcha_vars as $captcha_var)
+ {
+ $value = request_var($captcha_var, 0);
+ if ($value >= 0)
+ {
+ set_config($captcha_var, $value);
+ }
+ }
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
+ }
+ else if ($submit)
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
+ }
+ else
+ {
+ foreach ($this->captcha_vars as $captcha_var => $template_var)
+ {
+ $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var];
+ $template->assign_var($template_var, $var);
+ }
+
+ $template->assign_vars(array(
+ 'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
+ 'CAPTCHA_NAME' => $this->get_class_name(),
+ 'U_ACTION' => $module->u_action,
+ ));
+ }
+ }
+
+ function execute_demo()
+ {
+ global $config;
+
+ $config_old = $config;
+ foreach ($this->captcha_vars as $captcha_var => $template_var)
+ {
+ $config[$captcha_var] = request_var($captcha_var, (int) $config[$captcha_var]);
+ }
+ parent::execute_demo();
+ $config = $config_old;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php
new file mode 100644
index 0000000000..2f55d15efd
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php
@@ -0,0 +1,83 @@
+lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php
new file mode 100644
index 0000000000..ac30ed4297
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php
@@ -0,0 +1,72 @@
+lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action));
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php
new file mode 100644
index 0000000000..6f53e8c5ad
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php
@@ -0,0 +1,924 @@
+add_lang('captcha_qa');
+
+ // read input
+ $this->confirm_id = request_var('qa_confirm_id', '');
+ $this->answer = request_var('qa_answer', '', true);
+
+ $this->type = (int) $type;
+ $this->question_lang = $user->data['user_lang'];
+
+ // we need all defined questions - shouldn't be too many, so we can just grab them
+ // try the user's lang first
+ $sql = 'SELECT question_id
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'";
+ $result = $db->sql_query($sql, 3600);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $this->question_ids[$row['question_id']] = $row['question_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // fallback to the board default lang
+ if (!sizeof($this->question_ids))
+ {
+ $this->question_lang = $config['default_lang'];
+
+ $sql = 'SELECT question_id
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
+ $result = $db->sql_query($sql, 7200);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $this->question_ids[$row['question_id']] = $row['question_id'];
+ }
+ $db->sql_freeresult($result);
+ }
+
+ // okay, if there is a confirm_id, we try to load that confirm's state
+ if (!strlen($this->confirm_id) || !$this->load_answer())
+ {
+ // we have no valid confirm ID, better get ready to ask something
+ $this->select_question();
+ }
+ }
+
+ /**
+ * API function
+ */
+ function &get_instance()
+ {
+ $instance =& new phpbb_captcha_qa();
+
+ return $instance;
+ }
+
+ /**
+ * See if the captcha has created its tables.
+ */
+ function is_installed()
+ {
+ global $db, $phpbb_root_path, $phpEx;
+
+ if (!class_exists('phpbb_db_tools'))
+ {
+ include("$phpbb_root_path/includes/db/db_tools.$phpEx");
+ }
+ $db_tool = new phpbb_db_tools($db);
+
+ return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang
+ */
+ function is_available()
+ {
+ global $config, $db, $phpbb_root_path, $phpEx, $user;
+
+ // load language file for pretty display in the ACP dropdown
+ $user->add_lang('captcha_qa');
+
+ if (!phpbb_captcha_qa::is_installed())
+ {
+ return false;
+ }
+
+ $sql = 'SELECT COUNT(question_id) as count
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ return ((bool) $row['count']);
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ /**
+ * API function
+ */
+ function get_name()
+ {
+ return 'CAPTCHA_QA';
+ }
+
+ /**
+ * API function
+ */
+ function get_class_name()
+ {
+ return 'phpbb_captcha_qa';
+ }
+
+ /**
+ * API function - not needed as we don't display an image
+ */
+ function execute_demo()
+ {
+ }
+
+ /**
+ * API function - not needed as we don't display an image
+ */
+ function execute()
+ {
+ }
+
+ /**
+ * API function - send the question to the template
+ */
+ function get_template()
+ {
+ global $template;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'QA_CONFIRM_QUESTION' => $this->question_text,
+ 'QA_CONFIRM_ID' => $this->confirm_id,
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ ));
+
+ return 'captcha_qa.html';
+ }
+ }
+
+ /**
+ * API function - we just display a mockup so that the captcha doesn't need to be installed
+ */
+ function get_demo_template()
+ {
+ return 'captcha_qa_acp_demo.html';
+ }
+
+ /**
+ * API function
+ */
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['qa_answer'] = $this->answer;
+ }
+ $hidden_fields['qa_confirm_id'] = $this->confirm_id;
+
+ return $hidden_fields;
+ }
+
+ /**
+ * API function
+ */
+ function garbage_collect($type)
+ {
+ global $db, $config;
+
+ $sql = 'SELECT DISTINCT c.session_id
+ FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' c
+ LEFT JOIN ' . SESSIONS_TABLE . ' s
+ ON (c.session_id = s.session_id)
+ WHERE s.session_id IS NULL' .
+ ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
+ $result = $db->sql_query($sql);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ $sql_in = array();
+
+ do
+ {
+ $sql_in[] = (string) $row['session_id'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ if (sizeof($sql_in))
+ {
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ WHERE ' . $db->sql_in_set('session_id', $sql_in);
+ $db->sql_query($sql);
+ }
+ }
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * API function - we don't drop the tables here, as that would cause the loss of all entered questions.
+ */
+ function uninstall()
+ {
+ $this->garbage_collect(0);
+ }
+
+ /**
+ * API function - set up shop
+ */
+ function install()
+ {
+ global $db, $phpbb_root_path, $phpEx;
+
+ if (!class_exists('phpbb_db_tools'))
+ {
+ include("$phpbb_root_path/includes/db/db_tools.$phpEx");
+ }
+ $db_tool = new phpbb_db_tools($db);
+
+ $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE);
+
+ $schemas = array(
+ CAPTCHA_QUESTIONS_TABLE => array (
+ 'COLUMNS' => array(
+ 'question_id' => array('UINT', Null, 'auto_increment'),
+ 'strict' => array('BOOL', 0),
+ 'lang_id' => array('UINT', 0),
+ 'lang_iso' => array('VCHAR:30', ''),
+ 'question_text' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'question_id',
+ 'KEYS' => array(
+ 'lang_iso' => array('INDEX', 'lang_iso'),
+ ),
+ ),
+ CAPTCHA_ANSWERS_TABLE => array (
+ 'COLUMNS' => array(
+ 'question_id' => array('UINT', 0),
+ 'answer_text' => array('STEXT_UNI', ''),
+ ),
+ 'KEYS' => array(
+ 'question_id' => array('INDEX', 'question_id'),
+ ),
+ ),
+ CAPTCHA_QA_CONFIRM_TABLE => array (
+ 'COLUMNS' => array(
+ 'session_id' => array('CHAR:32', ''),
+ 'confirm_id' => array('CHAR:32', ''),
+ 'lang_iso' => array('VCHAR:30', ''),
+ 'question_id' => array('UINT', 0),
+ 'attempts' => array('UINT', 0),
+ 'confirm_type' => array('USINT', 0),
+ ),
+ 'KEYS' => array(
+ 'session_id' => array('INDEX', 'session_id'),
+ 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')),
+ ),
+ 'PRIMARY_KEY' => 'confirm_id',
+ ),
+ );
+
+ foreach($schemas as $table => $schema)
+ {
+ if (!$db_tool->sql_table_exists($table))
+ {
+ $db_tool->sql_create_table($table, $schema);
+ }
+ }
+ }
+
+ /**
+ * API function - see what has to be done to validate
+ */
+ function validate()
+ {
+ global $config, $db, $user;
+
+ $error = '';
+
+ if (!$this->confirm_id)
+ {
+ $error = $user->lang['CONFIRM_QUESTION_WRONG'];
+ }
+ else
+ {
+ if ($this->check_answer())
+ {
+ // $this->delete_code(); commented out to allow posting.php to repeat the question
+ $this->solved = true;
+ }
+ else
+ {
+ $error = $user->lang['CONFIRM_QUESTION_WRONG'];
+ }
+ }
+
+ if (strlen($error))
+ {
+ // okay, incorrect answer. Let's ask a new question.
+ $this->new_attempt();
+ $this->solved = false;
+
+ return $error;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Select a question
+ */
+ function select_question()
+ {
+ global $db, $user;
+
+ $this->confirm_id = md5(unique_id($user->ip));
+ $this->question = (int) array_rand($this->question_ids);
+
+ $sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'confirm_id' => (string) $this->confirm_id,
+ 'session_id' => (string) $user->session_id,
+ 'lang_iso' => (string) $this->question_lang,
+ 'confirm_type' => (int) $this->type,
+ 'question_id' => (int) $this->question,
+ ));
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+ /**
+ * New Question, if desired.
+ */
+ function reselect_question()
+ {
+ global $db, $user;
+
+ $this->question = (int) array_rand($this->question_ids);
+ $this->solved = 0;
+
+ $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ SET question_id = ' . (int) $this->question . "
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'";
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+ /**
+ * Wrong answer, so we increase the attempts and use a different question.
+ */
+ function new_attempt()
+ {
+ global $db, $user;
+
+ // yah, I would prefer a stronger rand, but this should work
+ $this->question = (int) array_rand($this->question_ids);
+ $this->solved = 0;
+
+ $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . '
+ SET question_id = ' . (int) $this->question . ",
+ attempts = attempts + 1
+ WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'";
+ $db->sql_query($sql);
+
+ $this->load_answer();
+ }
+
+ /**
+ * Look up everything we need and populate the instance variables.
+ */
+ function load_answer()
+ {
+ global $db, $user;
+
+ $sql = 'SELECT con.question_id, attempts, question_text, strict
+ FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes
+ WHERE con.question_id = qes.question_id
+ AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "'
+ AND confirm_type = " . $this->type;
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
+ {
+ $this->question = $row['question_id'];
+
+ $this->attempts = $row['attempts'];
+ $this->question_strict = $row['strict'];
+ $this->question_text = $row['question_text'];
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * The actual validation
+ */
+ function check_answer()
+ {
+ global $db;
+
+ $answer = ($this->question_strict) ? request_var('qa_answer', '', true) : utf8_clean_string(request_var('qa_answer', '', true));
+
+ $sql = 'SELECT answer_text
+ FROM ' . CAPTCHA_ANSWERS_TABLE . '
+ WHERE question_id = ' . (int) $this->question;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']);
+
+ if ($solution === $answer)
+ {
+ $this->solved = true;
+
+ break;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $this->solved;
+ }
+
+ /**
+ * API function - clean the entry
+ */
+ function delete_code()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . "
+ WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
+ AND session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . $this->type;
+ $db->sql_query($sql);
+ }
+
+ /**
+ * API function
+ */
+ function get_attempt_count()
+ {
+ return $this->attempts;
+ }
+
+ /**
+ * API function
+ */
+ function reset()
+ {
+ global $db, $user;
+
+ $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . "
+ WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
+ AND confirm_type = " . (int) $this->type;
+ $db->sql_query($sql);
+
+ // we leave the class usable by generating a new question
+ $this->select_question();
+ }
+
+ /**
+ * API function
+ */
+ function is_solved()
+ {
+ if (request_var('qa_answer', false) && $this->solved === 0)
+ {
+ $this->validate();
+ }
+
+ return (bool) $this->solved;
+ }
+
+ /**
+ * API function - The ACP backend, this marks the end of the easy methods
+ */
+ function acp_page($id, &$module)
+ {
+ global $db, $user, $auth, $template;
+ global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+
+ $user->add_lang('acp/board');
+ $user->add_lang('captcha_qa');
+
+ if (!$this->is_installed())
+ {
+ $this->install();
+ }
+
+ $module->tpl_name = 'captcha_qa_acp';
+ $module->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('submit', false);
+ $question_id = request_var('question_id', 0);
+ $action = request_var('action', '');
+
+ // we have two pages, so users might want to navigate from one to the other
+ $list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_class_name();
+
+ $template->assign_vars(array(
+ 'U_ACTION' => $module->u_action,
+ 'QUESTION_ID' => $question_id ,
+ 'CLASS' => $this->get_class_name(),
+ ));
+
+ // show the list?
+ if (!$question_id && $action != 'add')
+ {
+ $this->acp_question_list($module);
+ }
+ else if ($question_id && $action == 'delete')
+ {
+ if (confirm_box(true))
+ {
+ $this->acp_delete_question($question_id);
+
+ trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url));
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'question_id' => $question_id,
+ 'action' => $action,
+ 'configure' => 1,
+ 'select_captcha' => $this->get_class_name(),
+ ))
+ );
+ }
+ }
+ else
+ {
+ // okay, show the editor
+ $error = false;
+ $input_question = request_var('question_text', '', true);
+ $input_answers = request_var('answers', '', true);
+ $input_lang = request_var('lang_iso', '', true);
+ $input_strict = request_var('strict', false);
+ $langs = $this->get_languages();
+
+ foreach ($langs as $lang => $entry)
+ {
+ $template->assign_block_vars('langs', array(
+ 'ISO' => $lang,
+ 'NAME' => $entry['name'],
+ ));
+ }
+
+ $template->assign_vars(array(
+ 'U_LIST' => $list_url,
+ ));
+
+ if ($question_id)
+ {
+ if ($question = $this->acp_get_question_data($question_id))
+ {
+ $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']);
+
+ $template->assign_vars(array(
+ 'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'],
+ 'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'],
+ 'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'],
+ 'ANSWERS' => $answers,
+ ));
+ }
+ else
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
+ }
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'QUESTION_TEXT' => $input_question,
+ 'LANG_ISO' => $input_lang,
+ 'STRICT' => $input_strict,
+ 'ANSWERS' => $input_answers,
+ ));
+ }
+
+ if ($submit && check_form_key($form_key))
+ {
+ $data = $this->acp_get_question_input();
+
+ if (!$this->validate_input($data))
+ {
+ $template->assign_vars(array(
+ 'S_ERROR' => true,
+ ));
+ }
+ else
+ {
+ if ($question_id)
+ {
+ $this->acp_update_question($data, $question_id);
+ }
+ else
+ {
+ $this->acp_add_question($data);
+ }
+
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url));
+ }
+ }
+ else if ($submit)
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url));
+ }
+ }
+ }
+
+ /**
+ * This handles the list overview
+ */
+ function acp_question_list(&$module)
+ {
+ global $db, $template;
+
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_QUESTIONS_TABLE;
+ $result = $db->sql_query($sql);
+
+ $template->assign_vars(array(
+ 'S_LIST' => true,
+ ));
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_class_name() . '&';
+
+ $template->assign_block_vars('questions', array(
+ 'QUESTION_TEXT' => $row['question_text'],
+ 'QUESTION_ID' => $row['question_id'],
+ 'QUESTION_LANG' => $row['lang_iso'],
+ 'U_DELETE' => "{$url}action=delete",
+ 'U_EDIT' => "{$url}action=edit",
+ ));
+ }
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * Grab a question and bring it into a format the editor understands
+ */
+ function acp_get_question_data($question_id)
+ {
+ global $db;
+
+ if ($question_id)
+ {
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_QUESTIONS_TABLE . '
+ WHERE question_id = ' . $question_id;
+ $result = $db->sql_query($sql);
+ $question = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!$question)
+ {
+ return false;
+ }
+
+ $question['answers'] = array();
+
+ $sql = 'SELECT *
+ FROM ' . CAPTCHA_ANSWERS_TABLE . '
+ WHERE question_id = ' . $question_id;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $question['answers'][] = $row['answer_text'];
+ }
+ $db->sql_freeresult($result);
+
+ return $question;
+ }
+ }
+
+ /**
+ * Grab a question from input and bring it into a format the editor understands
+ */
+ function acp_get_question_input()
+ {
+ $question = array(
+ 'question_text' => request_var('question_text', '', true),
+ 'strict' => request_var('strict', false),
+ 'lang_iso' => request_var('lang_iso', ''),
+ 'answers' => explode("\n", request_var('answers', '', true)),
+ );
+
+ return $question;
+ }
+
+ /**
+ * Update a question.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_update_question($data, $question_id)
+ {
+ global $db, $cache;
+
+ // easier to delete all answers than to figure out which to update
+ $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id";
+ $db->sql_query($sql);
+
+ $langs = $this->get_languages();
+ $question_ary = $data;
+ $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id'];
+ unset($question_ary['answers']);
+
+ $sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $question_ary) . "
+ WHERE question_id = $question_id";
+ $db->sql_query($sql);
+
+ $this->acp_insert_answers($data, $question_id);
+
+ $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * Insert a question.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_add_question($data)
+ {
+ global $db, $cache;
+
+ $langs = $this->get_languages();
+ $question_ary = $data;
+
+ $question_ary['lang_id'] = $langs[$data['lang_iso']]['id'];
+ unset($question_ary['answers']);
+
+ $sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary);
+ $db->sql_query($sql);
+
+ $question_id = $db->sql_nextid();
+
+ $this->acp_insert_answers($data, $question_id);
+
+ $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE);
+ }
+
+ /**
+ * Insert the answers.
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function acp_insert_answers($data, $question_id)
+ {
+ global $db, $cache;
+
+ foreach ($data['answers'] as $answer)
+ {
+ $answer_ary = array(
+ 'question_id' => $question_id,
+ 'answer_text' => $answer,
+ );
+
+ $sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary);
+ $db->sql_query($sql);
+ }
+
+ $cache->destroy('sql', CAPTCHA_ANSWERS_TABLE);
+ }
+
+ /**
+ * Delete a question.
+ */
+ function acp_delete_question($question_id)
+ {
+ global $db, $cache;
+
+ $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE);
+
+ foreach ($tables as $table)
+ {
+ $sql = "DELETE FROM $table
+ WHERE question_id = $question_id";
+ $db->sql_query($sql);
+ }
+
+ $cache->destroy('sql', $tables);
+ }
+
+ /**
+ * Check if the entered data can be inserted/used
+ * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data
+ */
+ function validate_input($question_data)
+ {
+ $langs = $this->get_languages();
+
+ if (!isset($question_data['lang_iso']) ||
+ !isset($question_data['question_text']) ||
+ !isset($question_data['strict']) ||
+ !isset($question_data['answers']))
+ {
+ return false;
+ }
+
+ if (!isset($langs[$question_data['lang_iso']]) ||
+ !$question_data['question_text'] ||
+ !sizeof($question_data['answers']))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * List the installed language packs
+ */
+ function get_languages()
+ {
+ global $db;
+
+ $sql = 'SELECT *
+ FROM ' . LANG_TABLE;
+ $result = $db->sql_query($sql);
+
+ $langs = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $langs[$row['lang_iso']] = array(
+ 'name' => $row['lang_local_name'],
+ 'id' => (int) $row['lang_id'],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ return $langs;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
new file mode 100644
index 0000000000..2d37b13a4f
--- /dev/null
+++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
@@ -0,0 +1,334 @@
+add_lang('captcha_recaptcha');
+ parent::init($type);
+ $this->challenge = request_var('recaptcha_challenge_field', '');
+ $this->response = request_var('recaptcha_response_field', '');
+ }
+
+ function &get_instance()
+ {
+ $instance =& new phpbb_recaptcha();
+ return $instance;
+ }
+
+ function is_available()
+ {
+ global $config, $user;
+ $user->add_lang('captcha_recaptcha');
+ return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey']));
+ }
+
+ /**
+ * API function
+ */
+ function has_config()
+ {
+ return true;
+ }
+
+ function get_name()
+ {
+ return 'CAPTCHA_RECAPTCHA';
+ }
+
+ function get_class_name()
+ {
+ return 'phpbb_recaptcha';
+ }
+
+ function acp_page($id, &$module)
+ {
+ global $config, $db, $template, $user;
+
+ $captcha_vars = array(
+ 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
+ 'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY',
+ );
+
+ $module->tpl_name = 'captcha_recaptcha_acp';
+ $module->page_title = 'ACP_VC_SETTINGS';
+ $form_key = 'acp_captcha';
+ add_form_key($form_key);
+
+ $submit = request_var('submit', '');
+
+ if ($submit && check_form_key($form_key))
+ {
+ $captcha_vars = array_keys($captcha_vars);
+ foreach ($captcha_vars as $captcha_var)
+ {
+ $value = request_var($captcha_var, '');
+ if ($value)
+ {
+ set_config($captcha_var, $value);
+ }
+ }
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action));
+ }
+ else if ($submit)
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action));
+ }
+ else
+ {
+ foreach ($captcha_vars as $captcha_var => $template_var)
+ {
+ $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : '');
+ $template->assign_var($template_var, $var);
+ }
+
+ $template->assign_vars(array(
+ 'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
+ 'CAPTCHA_NAME' => $this->get_class_name(),
+ 'U_ACTION' => $module->u_action,
+ ));
+
+ }
+ }
+
+ // not needed
+ function execute_demo()
+ {
+ }
+
+ // not needed
+ function execute()
+ {
+ }
+
+ function get_template()
+ {
+ global $config, $user, $template;
+
+ if ($this->is_solved())
+ {
+ return false;
+ }
+ else
+ {
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '
', '');
+
+ $template->assign_vars(array(
+ 'RECAPTCHA_SERVER' => $this->recaptcha_server,
+ 'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
+ 'RECAPTCHA_ERRORGET' => '',
+ 'S_RECAPTCHA_AVAILABLE' => $this->is_available(),
+ 'S_CONFIRM_CODE' => true,
+ 'S_TYPE' => $this->type,
+ 'L_CONFIRM_EXPLAIN' => $explain,
+ ));
+
+ return 'captcha_recaptcha.html';
+ }
+ }
+
+ function get_demo_template($id)
+ {
+ return $this->get_template();
+ }
+
+ function get_hidden_fields()
+ {
+ $hidden_fields = array();
+
+ // this is required for posting.php - otherwise we would forget about the captcha being already solved
+ if ($this->solved)
+ {
+ $hidden_fields['confirm_code'] = $this->code;
+ }
+ $hidden_fields['confirm_id'] = $this->confirm_id;
+ return $hidden_fields;
+ }
+
+ function uninstall()
+ {
+ $this->garbage_collect(0);
+ }
+
+ function install()
+ {
+ return;
+ }
+
+ function validate()
+ {
+ if (!parent::validate())
+ {
+ return false;
+ }
+ else
+ {
+ return $this->recaptcha_check_answer();
+ }
+ }
+
+// Code from here on is based on recaptchalib.php
+/*
+ * This is a PHP library that handles calling reCAPTCHA.
+ * - Documentation and latest version
+ * http://recaptcha.net/plugins/php/
+ * - Get a reCAPTCHA API Key
+ * http://recaptcha.net/api/getkey
+ * - Discussion group
+ * http://groups.google.com/group/recaptcha
+ *
+ * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
+ * AUTHORS:
+ * Mike Crawford
+ * Ben Maurer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+ /**
+ * Submits an HTTP POST to a reCAPTCHA server
+ * @param string $host
+ * @param string $path
+ * @param array $data
+ * @param int port
+ * @return array response
+ */
+ function _recaptcha_http_post($host, $path, $data, $port = 80)
+ {
+ $req = $this->_recaptcha_qsencode ($data);
+
+ $http_request = "POST $path HTTP/1.0\r\n";
+ $http_request .= "Host: $host\r\n";
+ $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+ $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+ $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n";
+ $http_request .= "\r\n";
+ $http_request .= $req;
+
+ $response = '';
+ if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
+ {
+ trigger_error('Could not open socket', E_USER_ERROR);
+ }
+
+ fwrite($fs, $http_request);
+
+ while (!feof($fs))
+ {
+ // One TCP-IP packet
+ $response .= fgets($fs, 1160);
+ }
+ fclose($fs);
+ $response = explode("\r\n\r\n", $response, 2);
+
+ return $response;
+ }
+
+ /**
+ * Calls an HTTP POST function to verify if the user's guess was correct
+ * @param array $extra_params an array of extra variables to post to the server
+ * @return ReCaptchaResponse
+ */
+ function recaptcha_check_answer($extra_params = array())
+ {
+ global $config, $user;
+
+ //discard spam submissions
+ if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0)
+ {
+ return $user->lang['RECAPTCHA_INCORRECT'];
+ }
+
+ $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, '/verify',
+ array(
+ 'privatekey' => $config['recaptcha_privkey'],
+ 'remoteip' => $user->ip,
+ 'challenge' => $this->challenge,
+ 'response' => $this->response
+ ) + $extra_params
+ );
+
+ $answers = explode("\n", $response[1]);
+
+ if (trim($answers[0]) === 'true')
+ {
+ $this->solved = true;
+ return false;
+ }
+ else
+ {
+ if ($answers[1] === 'incorrect-captcha-sol')
+ {
+ return $user->lang['RECAPTCHA_INCORRECT'];
+ }
+ }
+ }
+
+ /**
+ * Encodes the given data into a query string format
+ * @param $data - array of string elements to be encoded
+ * @return string - encoded request
+ */
+ function _recaptcha_qsencode($data)
+ {
+ $req = '';
+ foreach ($data as $key => $value)
+ {
+ $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
+ }
+
+ // Cut the last '&'
+ $req = substr($req, 0, strlen($req) - 1);
+ return $req;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index 4cb21bc637..a526b9bf71 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*/
// phpBB Version
-define('PHPBB_VERSION', '3.0.5');
+define('PHPBB_VERSION', '3.0.6-RC1');
// QA-related
// define('PHPBB_QA', 1);
@@ -91,6 +91,11 @@ define('FORUM_FLAG_PRUNE_ANNOUNCE', 4);
define('FORUM_FLAG_PRUNE_STICKY', 8);
define('FORUM_FLAG_ACTIVE_TOPICS', 16);
define('FORUM_FLAG_POST_REVIEW', 32);
+define('FORUM_FLAG_QUICK_REPLY', 64);
+
+// Forum Options... sequential order. Modifications should begin at number 10 (number 29 is maximum)
+define('FORUM_OPTION_FEED_NEWS', 1);
+define('FORUM_OPTION_FEED_EXCLUDE', 2);
// Optional text flags
define('OPTION_FLAG_BBCODE', 1);
@@ -160,6 +165,9 @@ define('BBCODE_UID_LEN', 8);
// Number of core BBCodes
define('NUM_CORE_BBCODES', 12);
+// Smiley hard limit
+define('SMILEY_LIMIT', 1000);
+
// Magic url types
define('MAGIC_URL_EMAIL', 1);
define('MAGIC_URL_FULL', 2);
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php
index bc6b027b1f..ddc633c6d1 100644
--- a/phpBB/includes/db/db_tools.php
+++ b/phpBB/includes/db/db_tools.php
@@ -347,6 +347,11 @@ class phpbb_db_tools
// holds the DDL for a column
$columns = $statements = array();
+ if ($this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
// Begin transaction
$statements[] = 'begin';
@@ -580,6 +585,14 @@ class phpbb_db_tools
}
$statements = array();
+ $sqlite = false;
+
+ // For SQLite we need to perform the schema changes in a much more different way
+ if ($this->db->sql_layer == 'sqlite' && $this->return_statements)
+ {
+ $sqlite_data = array();
+ $sqlite = true;
+ }
// Change columns?
if (!empty($schema_changes['change_columns']))
@@ -589,16 +602,27 @@ class phpbb_db_tools
foreach ($columns as $column_name => $column_data)
{
// If the column exists we change it, else we add it ;)
- if ($this->sql_column_exists($table, $column_name))
+ if ($column_exists = $this->sql_column_exists($table, $column_name))
{
- $result = $this->sql_column_change($table, $column_name, $column_data);
+ $result = $this->sql_column_change($table, $column_name, $column_data, true);
}
else
{
- $result = $this->sql_column_add($table, $column_name, $column_data);
+ $result = $this->sql_column_add($table, $column_name, $column_data, true);
}
- if ($this->return_statements)
+ if ($sqlite)
+ {
+ if ($column_exists)
+ {
+ $sqlite_data[$table]['change_columns'][] = $result;
+ }
+ else
+ {
+ $sqlite_data[$table]['add_columns'][] = $result;
+ }
+ }
+ else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@@ -614,16 +638,27 @@ class phpbb_db_tools
foreach ($columns as $column_name => $column_data)
{
// Only add the column if it does not exist yet, else change it (to be consistent)
- if ($this->sql_column_exists($table, $column_name))
+ if ($column_exists = $this->sql_column_exists($table, $column_name))
{
- $result = $this->sql_column_change($table, $column_name, $column_data);
+ $result = $this->sql_column_change($table, $column_name, $column_data, true);
}
else
{
- $result = $this->sql_column_add($table, $column_name, $column_data);
+ $result = $this->sql_column_add($table, $column_name, $column_data, true);
}
- if ($this->return_statements)
+ if ($sqlite)
+ {
+ if ($column_exists)
+ {
+ $sqlite_data[$table]['change_columns'][] = $result;
+ }
+ else
+ {
+ $sqlite_data[$table]['add_columns'][] = $result;
+ }
+ }
+ else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@@ -658,9 +693,13 @@ class phpbb_db_tools
// Only remove the column if it exists...
if ($this->sql_column_exists($table, $column))
{
- $result = $this->sql_column_remove($table, $column);
+ $result = $this->sql_column_remove($table, $column, true);
- if ($this->return_statements)
+ if ($sqlite)
+ {
+ $sqlite_data[$table]['drop_columns'][] = $result;
+ }
+ else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@@ -674,9 +713,13 @@ class phpbb_db_tools
{
foreach ($schema_changes['add_primary_keys'] as $table => $columns)
{
- $result = $this->sql_create_primary_key($table, $columns);
+ $result = $this->sql_create_primary_key($table, $columns, true);
- if ($this->return_statements)
+ if ($sqlite)
+ {
+ $sqlite_data[$table]['primary_key'] = $result;
+ }
+ else if ($this->return_statements)
{
$statements = array_merge($statements, $result);
}
@@ -717,6 +760,147 @@ class phpbb_db_tools
}
}
+ if ($sqlite)
+ {
+ foreach ($sqlite_data as $table_name => $sql_schema_changes)
+ {
+ // Create temporary table with original data
+ $statements[] = 'begin';
+
+ $sql = "SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table'
+ AND name = '{$table_name}'
+ ORDER BY type DESC, name;";
+ $result = $this->db->sql_query($sql);
+
+ if (!$result)
+ {
+ continue;
+ }
+
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ // Create a backup table and populate it, destroy the existing one
+ $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']);
+ $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name;
+ $statements[] = 'DROP TABLE ' . $table_name;
+
+ // Get the columns...
+ preg_match('#\((.*)\)#s', $row['sql'], $matches);
+
+ $plain_table_cols = trim($matches[1]);
+ $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols);
+ $column_list = array();
+
+ foreach ($new_table_cols as $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ continue;
+ }
+ $column_list[] = $entities[0];
+ }
+
+ // note down the primary key notation because sqlite only supports adding it to the end for the new table
+ $primary_key = false;
+ $_new_cols = array();
+
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if ($entities[0] == 'PRIMARY')
+ {
+ $primary_key = $declaration;
+ continue;
+ }
+ $_new_cols[] = $declaration;
+ }
+
+ $new_table_cols = $_new_cols;
+
+ // First of all... change columns
+ if (!empty($sql_schema_changes['change_columns']))
+ {
+ foreach ($sql_schema_changes['change_columns'] as $column_sql)
+ {
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if (strpos($column_sql, $entities[0] . ' ') === 0)
+ {
+ $new_table_cols[$key] = $column_sql;
+ }
+ }
+ }
+ }
+
+ if (!empty($sql_schema_changes['add_columns']))
+ {
+ foreach ($sql_schema_changes['add_columns'] as $column_sql)
+ {
+ $new_table_cols[] = $column_sql;
+ }
+ }
+
+ // Now drop them...
+ if (!empty($sql_schema_changes['drop_columns']))
+ {
+ foreach ($sql_schema_changes['drop_columns'] as $column_name)
+ {
+ // Remove from column list...
+ $new_column_list = array();
+ foreach ($column_list as $key => $value)
+ {
+ if ($value === $column_name)
+ {
+ continue;
+ }
+
+ $new_column_list[] = $value;
+ }
+
+ $column_list = $new_column_list;
+
+ // Remove from table...
+ $_new_cols = array();
+ foreach ($new_table_cols as $key => $declaration)
+ {
+ $entities = preg_split('#\s+#', trim($declaration));
+ if (strpos($column_name . ' ', $entities[0] . ' ') === 0)
+ {
+ continue;
+ }
+ $_new_cols[] = $declaration;
+ }
+ $new_table_cols = $_new_cols;
+ }
+ }
+
+ // Primary key...
+ if (!empty($sql_schema_changes['primary_key']))
+ {
+ $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')';
+ }
+ // Add a new one or the old primary key
+ else if ($primary_key !== false)
+ {
+ $new_table_cols[] = $primary_key;
+ }
+
+ $columns = implode(',', $column_list);
+
+ // create a new table and fill it up. destroy the temp one
+ $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');';
+ $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;';
+ $statements[] = 'DROP TABLE ' . $table_name . '_temp';
+
+ $statements[] = 'commit';
+ }
+ }
+
if ($this->return_statements)
{
return $statements;
@@ -801,7 +985,7 @@ class phpbb_db_tools
case 'oracle':
$sql = "SELECT column_name
FROM user_tab_columns
- WHERE table_name = '{$table}'";
+ WHERE LOWER(table_name) = '" . strtolower($table) . "'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
@@ -819,7 +1003,7 @@ class phpbb_db_tools
case 'firebird':
$sql = "SELECT RDB\$FIELD_NAME as FNAME
FROM RDB\$RELATION_FIELDS
- WHERE RDB\$RELATION_NAME = '{$table}'";
+ WHERE RDB\$RELATION_NAME = '" . strtoupper($table) . "'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
@@ -972,10 +1156,12 @@ class phpbb_db_tools
{
case 'firebird':
$sql .= " {$column_type} ";
+ $return_array['column_type_sql_type'] = " {$column_type} ";
if (!is_null($column_data[1]))
{
$sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
+ $return_array['column_type_sql_default'] = ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
}
$sql .= 'NOT NULL';
@@ -1129,7 +1315,7 @@ class phpbb_db_tools
/**
* Add new column
*/
- function sql_column_add($table_name, $column_name, $column_data)
+ function sql_column_add($table_name, $column_name, $column_data, $inline = false)
{
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
$statements = array();
@@ -1158,6 +1344,12 @@ class phpbb_db_tools
break;
case 'sqlite':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column_name . ' ' . $column_data['column_type_sql'];
+ }
+
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
$sql = "SELECT sql
@@ -1222,7 +1414,7 @@ class phpbb_db_tools
/**
* Drop column
*/
- function sql_column_remove($table_name, $column_name)
+ function sql_column_remove($table_name, $column_name, $inline = false)
{
$statements = array();
@@ -1250,6 +1442,12 @@ class phpbb_db_tools
break;
case 'sqlite':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column_name;
+ }
+
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
$sql = "SELECT sql
@@ -1292,7 +1490,7 @@ class phpbb_db_tools
$columns = implode(',', $column_list);
- $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
+ $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
// create a new table and fill it up. destroy the temp one
$statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');';
@@ -1347,6 +1545,11 @@ class phpbb_db_tools
{
$statements = array();
+ if (!$this->sql_table_exists($table_name))
+ {
+ return $this->_sql_run_sql($statements);
+ }
+
// the most basic operation, get rid of the table
$statements[] = 'DROP TABLE ' . $table_name;
@@ -1405,7 +1608,7 @@ class phpbb_db_tools
/**
* Add primary key
*/
- function sql_create_primary_key($table_name, $column)
+ function sql_create_primary_key($table_name, $column, $inline = false)
{
$statements = array();
@@ -1432,6 +1635,12 @@ class phpbb_db_tools
break;
case 'sqlite':
+
+ if ($inline && $this->return_statements)
+ {
+ return $column;
+ }
+
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
@@ -1639,7 +1848,7 @@ class phpbb_db_tools
/**
* Change column type (not name!)
*/
- function sql_column_change($table_name, $column_name, $column_data)
+ function sql_column_change($table_name, $column_name, $column_data, $inline = false)
{
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
$statements = array();
@@ -1648,7 +1857,15 @@ class phpbb_db_tools
{
case 'firebird':
// Change type...
- $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql'];
+ if (!empty($column_data['column_type_sql_default']))
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type'];
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default'];
+ }
+ else
+ {
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql'];
+ }
break;
case 'mssql':
@@ -1729,6 +1946,11 @@ class phpbb_db_tools
case 'sqlite':
+ if ($inline && $this->return_statements)
+ {
+ return $column_name . ' ' . $column_data['column_type_sql'];
+ }
+
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php
index b530a572da..a962696bb8 100644
--- a/phpBB/includes/db/dbal.php
+++ b/phpBB/includes/db/dbal.php
@@ -235,8 +235,8 @@ class dbal
*/
function sql_like_expression($expression)
{
- $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression);
- $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
+ $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression);
+ $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\'');
}
@@ -411,6 +411,24 @@ class dbal
}
}
+ /**
+ * Run binary AND operator on DB column.
+ * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}"
+ *
+ * @param string $column_name The column name to use
+ * @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29
+ * @param string $compare Any custom SQL code after the check (for example "= 0")
+ */
+ function sql_bit_and($column_name, $bit, $compare = '')
+ {
+ if (method_exists($this, '_sql_bit_and'))
+ {
+ return $this->_sql_bit_and($column_name, $bit, $compare);
+ }
+
+ return $column_name . ' & ' . (1 << $bit) . (($compare) ? ' ' . $compare : '');
+ }
+
/**
* Run more than one insert statement.
*
@@ -435,8 +453,7 @@ class dbal
// If by accident the sql array is only one-dimensional we build a normal insert statement
if (!is_array($_sql_ary))
{
- $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary));
- return true;
+ return $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary));
}
$values = array();
@@ -447,7 +464,7 @@ class dbal
$ary[] = '(' . implode(', ', $values) . ')';
}
- $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary));
+ return $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary));
}
else
{
@@ -458,7 +475,12 @@ class dbal
return false;
}
- $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
+ $result = $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
+
+ if (!$result)
+ {
+ return false;
+ }
}
}
diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php
index 3b31942a8b..fb1ef44c55 100644
--- a/phpBB/includes/db/firebird.php
+++ b/phpBB/includes/db/firebird.php
@@ -20,7 +20,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Firebird/Interbase Database Abstraction Layer
-* Minimum Requirement is Firebird 2.0
+* Minimum Requirement is Firebird 2.1
* @package dbal
*/
class dbal_firebird extends dbal
@@ -72,7 +72,7 @@ class dbal_firebird extends dbal
return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION);
}
- return ($raw) ? '2.0' : 'Firebird/Interbase';
+ return ($raw) ? '2.1' : 'Firebird/Interbase';
}
/**
@@ -446,6 +446,11 @@ class dbal_firebird extends dbal
return $data;
}
+ function _sql_bit_and($column_name, $bit, $compare = '')
+ {
+ return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
+ }
+
/**
* return sql error array
* @access private
diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php
index a140c4b676..10f4a1a7a7 100644
--- a/phpBB/includes/db/oracle.php
+++ b/phpBB/includes/db/oracle.php
@@ -568,6 +568,11 @@ class dbal_oracle extends dbal
return $data;
}
+ function _sql_bit_and($column_name, $bit, $compare = '')
+ {
+ return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
+ }
+
/**
* return sql error array
* @access private
diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php
index eb0dcce395..e9f0e41b75 100644
--- a/phpBB/includes/diff/engine.php
+++ b/phpBB/includes/diff/engine.php
@@ -49,6 +49,8 @@ if (!defined('IN_PHPBB'))
*/
class diff_engine
{
+ var $skip_whitespace_changes = true;
+
function diff(&$from_lines, &$to_lines, $preserve_cr = true)
{
// Remove empty lines...
@@ -176,6 +178,20 @@ class diff_engine
$add[] = $to_lines[$yi++];
}
+ // Here we are a bit naughty. Naughty Boy... Naughty Boy...
+ // We check if delete and add is filled and only consist of one item
+ if ($this->skip_whitespace_changes && sizeof($delete) == 1 && sizeof($add) == 1)
+ {
+ // Now we simply trim the string and see if the lines are identical
+ // If they are identical we do not need to take them into account for the merge (less conflicts in phpBB)
+ if (trim($delete[0]) === trim($add[0]))
+ {
+ // This line ensures the line found here is correctly copied later (remember: we naughty boys like loops)
+ $xi--; $yi--; $this->xchanged[$xi] = $this->ychanged[$yi] = false;
+ $delete = $add = array();
+ }
+ }
+
if ($delete && $add)
{
$edits[] = new diff_op_change($delete, $add);
diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php
index 02fb6ccc37..5cb1b6ada9 100644
--- a/phpBB/includes/diff/renderer.php
+++ b/phpBB/includes/diff/renderer.php
@@ -536,7 +536,7 @@ class diff_renderer_raw extends diff_renderer
*/
function get_diff_content($diff)
{
- return '
';
+ return '
';
}
function _block_header($xbeg, $xlen, $ybeg, $ylen)
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 476565452c..092a5d5d86 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -71,12 +71,13 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false)
$_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
}
- if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
+ $super_global = ($cookie) ? '_COOKIE' : '_REQUEST';
+ if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default))
{
return (is_array($default)) ? array() : $default;
}
- $var = $_REQUEST[$var_name];
+ $var = $GLOBALS[$super_global][$var_name];
if (!is_array($default))
{
$type = gettype($default);
@@ -174,7 +175,7 @@ function set_config_count($config_name, $increment, $is_dynamic = false)
switch ($db->sql_layer)
{
case 'firebird':
- $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as CHAR)';
+ $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as VARCHAR(255))';
break;
case 'postgres':
@@ -231,27 +232,82 @@ function unique_id($extra = 'c')
/**
* Return formatted string for filesizes
+*
+* @param int $value filesize in bytes
+* @param bool $string_only true if language string should be returned
+* @param array $allowed_units only allow these units (data array indexes)
+*
+* @return mixed data array if $string_only is false
+* @author bantu
*/
-function get_formatted_filesize($bytes, $add_size_lang = true)
+function get_formatted_filesize($value, $string_only = true, $allowed_units = false)
{
global $user;
- if ($bytes >= pow(2, 30))
+ $available_units = array(
+ 'gb' => array(
+ 'min' => 1073741824, // pow(2, 30)
+ 'index' => 3,
+ 'si_unit' => 'GB',
+ 'iec_unit' => 'GIB',
+ ),
+ 'mb' => array(
+ 'min' => 1048576, // pow(2, 20)
+ 'index' => 2,
+ 'si_unit' => 'MB',
+ 'iec_unit' => 'MIB',
+ ),
+ 'kb' => array(
+ 'min' => 1024, // pow(2, 10)
+ 'index' => 1,
+ 'si_unit' => 'KB',
+ 'iec_unit' => 'KIB',
+ ),
+ 'b' => array(
+ 'min' => 0,
+ 'index' => 0,
+ 'si_unit' => 'BYTES', // Language index
+ 'iec_unit' => 'BYTES', // Language index
+ ),
+ );
+
+ foreach ($available_units as $si_identifier => $unit_info)
{
- return ($add_size_lang) ? round($bytes / 1024 / 1024 / 1024, 2) . ' ' . $user->lang['GIB'] : round($bytes / 1024 / 1024 / 1024, 2);
+ if (!empty($allowed_units) && $si_identifier != 'b' && !in_array($si_identifier, $allowed_units))
+ {
+ continue;
+ }
+
+ if ($value >= $unit_info['min'])
+ {
+ $unit_info['si_identifier'] = $si_identifier;
+
+ break;
+ }
+ }
+ unset($available_units);
+
+ for ($i = 0; $i < $unit_info['index']; $i++)
+ {
+ $value /= 1024;
+ }
+ $value = round($value, 2);
+
+ // Lookup units in language dictionary
+ $unit_info['si_unit'] = (isset($user->lang[$unit_info['si_unit']])) ? $user->lang[$unit_info['si_unit']] : $unit_info['si_unit'];
+ $unit_info['iec_unit'] = (isset($user->lang[$unit_info['iec_unit']])) ? $user->lang[$unit_info['iec_unit']] : $unit_info['iec_unit'];
+
+ // Default to IEC
+ $unit_info['unit'] = $unit_info['iec_unit'];
+
+ if (!$string_only)
+ {
+ $unit_info['value'] = $value;
+
+ return $unit_info;
}
- if ($bytes >= pow(2, 20))
- {
- return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . $user->lang['MIB'] : round($bytes / 1024 / 1024, 2);
- }
-
- if ($bytes >= pow(2, 10))
- {
- return ($add_size_lang) ? round($bytes / 1024, 2) . ' ' . $user->lang['KIB'] : round($bytes / 1024, 2);
- }
-
- return ($add_size_lang) ? ($bytes) . ' ' . $user->lang['BYTES'] : ($bytes);
+ return $value . ' ' . $unit_info['unit'];
}
/**
@@ -495,6 +551,18 @@ function _hash_crypt_private($password, $setting, &$itoa64)
return $output;
}
+/**
+* Hashes an email address to a big integer
+*
+* @param string $email Email address
+*
+* @return string Big Integer
+*/
+function phpbb_email_hash($email)
+{
+ return crc32(strtolower($email)) . strlen($email);
+}
+
/**
* Global function for chmodding directories and files for internal use
*
@@ -669,6 +737,67 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)
return $result;
}
+/**
+* Test if a file/directory is writable
+*
+* This function calls the native is_writable() when not running under
+* Windows and it is not disabled.
+*
+* @param string $file Path to perform write test on
+* @return bool True when the path is writable, otherwise false.
+*/
+function phpbb_is_writable($file)
+{
+ if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable'))
+ {
+ if (file_exists($file))
+ {
+ // Canonicalise path to absolute path
+ $file = phpbb_realpath($file);
+
+ if (is_dir($file))
+ {
+ // Test directory by creating a file inside the directory
+ $result = @tempnam($file, 'i_w');
+
+ if (is_string($result) && file_exists($result))
+ {
+ unlink($result);
+
+ // Ensure the file is actually in the directory (returned realpathed)
+ return (strpos($result, $file) === 0) ? true : false;
+ }
+ }
+ else
+ {
+ $handle = @fopen($file, 'r+');
+
+ if (is_resource($handle))
+ {
+ fclose($handle);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // file does not exist test if we can write to the directory
+ $dir = dirname($file);
+
+ if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ else
+ {
+ return is_writable($file);
+ }
+}
+
// Compatibility functions
if (!function_exists('array_combine'))
@@ -1047,7 +1176,7 @@ function tz_select($default = '', $truncate = false)
if (is_numeric($offset))
{
$selected = ($offset == $default) ? ' selected="selected"' : '';
- $tz_select .= '
';
+ $tz_select .= '
';
}
}
@@ -1110,7 +1239,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
}
// Add 0 to forums array to mark global announcements correctly
- $forum_id[] = 0;
+ // $forum_id[] = 0;
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
@@ -1527,6 +1656,135 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
return $last_read;
}
+/**
+* Get list of unread topics
+*
+* @param int $user_id User ID (or false for current user)
+* @param string $sql_extra Extra WHERE SQL statement
+* @param string $sql_sort ORDER BY SQL sorting statement
+* @param string $sql_limit Limits the size of unread topics list, 0 for unlimited query
+*
+* @return array[int][int] Topic ids as keys, mark_time of topic as value
+*/
+function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001)
+{
+ global $config, $db, $user;
+
+ $user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id;
+
+ // Data array we're going to return
+ $unread_topics = array();
+
+ if (empty($sql_sort))
+ {
+ $sql_sort = 'ORDER BY t.topic_last_post_time DESC';
+ }
+
+ if ($config['load_db_lastread'] && $user->data['is_registered'])
+ {
+ // Get list of the unread topics
+ $last_mark = $user->data['user_lastmark'];
+
+ $sql_array = array(
+ 'SELECT' => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time',
+
+ 'FROM' => array(TOPICS_TABLE => 't'),
+
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'),
+ 'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id AND tt.mark_time > $last_mark",
+ ),
+ array(
+ 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'),
+ 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id AND ft.mark_time > $last_mark",
+ ),
+ ),
+
+ 'WHERE' => "
+ (
+ (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR
+ (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR
+ (
+ ((tt.mark_time IS NULL AND ft.mark_time IS NULL) OR (tt.mark_time < $last_mark AND ft.mark_time < $last_mark))
+ AND t.topic_last_post_time > $last_mark
+ )
+ )
+ $sql_extra
+ $sql_sort",
+ );
+
+ $sql = $db->sql_build_query('SELECT', $sql_array);
+ $result = $db->sql_query_limit($sql, $sql_limit);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_id = (int) $row['topic_id'];
+ $unread_topics[$topic_id] = ($row['topic_mark_time']) ? (int) $row['topic_mark_time'] : (($row['forum_mark_time']) ? (int) $row['forum_mark_time'] : $last_mark);
+ }
+ $db->sql_freeresult($result);
+ }
+ else if ($config['load_anon_lastread'] || $user->data['is_registered'])
+ {
+ global $tracking_topics;
+
+ if (empty($tracking_topics))
+ {
+ $tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true);
+ $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
+ }
+
+ if (!$user->data['is_registered'])
+ {
+ $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0;
+ }
+ else
+ {
+ $user_lastmark = (int) $user->data['user_lastmark'];
+ }
+
+ $sql = 'SELECT t.topic_id, t.forum_id, t.topic_last_post_time
+ FROM ' . TOPICS_TABLE . ' t
+ WHERE t.topic_last_post_time > ' . $user_lastmark . "
+ $sql_extra
+ $sql_sort";
+ $result = $db->sql_query_limit($sql, $sql_limit);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $forum_id = (int) $row['forum_id'];
+ $topic_id = (int) $row['topic_id'];
+ $topic_id36 = base_convert($topic_id, 10, 36);
+
+ if (isset($tracking_topics['t'][$topic_id36]))
+ {
+ $last_read = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate'];
+
+ if ($row['topic_last_post_time'] > $last_read)
+ {
+ $unread_topics[$topic_id] = $last_read;
+ }
+ }
+ else if (isset($tracking_topics['f'][$forum_id]))
+ {
+ $mark_time = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate'];
+
+ if ($row['topic_last_post_time'] > $mark_time)
+ {
+ $unread_topics[$topic_id] = $mark_time;
+ }
+ }
+ else
+ {
+ $unread_topics[$topic_id] = $user_lastmark;
+ }
+ }
+ $db->sql_freeresult($result);
+ }
+
+ return $unread_topics;
+}
+
/**
* Check for read forums and update topic tracking info accordingly
*
@@ -1777,7 +2035,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add
}
$on_page = floor($start_item / $per_page) + 1;
- $url_delim = (strpos($base_url, '?') === false) ? '?' : '&';
+ $url_delim = (strpos($base_url, '?') === false) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&');
$page_string = ($on_page == 1) ? '
1' : '
1';
@@ -2056,7 +2314,7 @@ function redirect($url, $return = false, $disable_cd_check = false)
$url = str_replace('&', '&', $url);
// Determine which type of redirect we need to handle...
- $url_parts = parse_url($url);
+ $url_parts = @parse_url($url);
if ($url_parts === false)
{
@@ -2200,17 +2458,12 @@ function reapply_sid($url)
}
// Remove previously added sid
- if (strpos($url, '?sid=') !== false)
+ if (strpos($url, 'sid=') !== false)
{
- $url = preg_replace('/(\?)sid=[a-z0-9]+(&|&)?/', '\1', $url);
- }
- else if (strpos($url, '&sid=') !== false)
- {
- $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
- }
- else if (strpos($url, '&sid=') !== false)
- {
- $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
+ // All kind of links
+ $url = preg_replace('/(\?)?(&|&)?sid=[a-z0-9]+/', '', $url);
+ // if the sid was the first param, make the old second as first ones
+ $url = preg_replace("/$phpEx(&|&)+?/", "$phpEx?", $url);
}
return append_sid($url);
@@ -2274,6 +2527,18 @@ function build_url($strip_vars = false)
$redirect .= ($query) ? '?' . $query : '';
}
+ // We need to be cautious here.
+ // On some situations, the redirect path is an absolute URL, sometimes a relative path
+ // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location,
+ // else we use the URL directly.
+ $url_parts = @parse_url($redirect);
+
+ // URL
+ if ($url_parts !== false && !empty($url_parts['scheme']) && !empty($url_parts['host']))
+ {
+ return str_replace('&', '&', $redirect);
+ }
+
return $phpbb_root_path . str_replace('&', '&', $redirect);
}
@@ -2435,7 +2700,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
if ($check && $confirm)
{
- $user_id = request_var('user_id', 0);
+ $user_id = request_var('confirm_uid', 0);
$session_id = request_var('sess', '');
$confirm_key = request_var('confirm_key', '');
@@ -2457,10 +2722,10 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
}
$s_hidden_fields = build_hidden_fields(array(
- 'user_id' => $user->data['user_id'],
- 'sess' => $user->session_id,
- 'sid' => $user->session_id)
- );
+ 'confirm_uid' => $user->data['user_id'],
+ 'sess' => $user->session_id,
+ 'sid' => $user->session_id,
+ ));
// generate activation key
$confirm_key = gen_rand_string(10);
@@ -2471,7 +2736,7 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
}
else
{
- page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]);
+ page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false);
}
$template->set_filenames(array(
@@ -2520,6 +2785,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{
global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config;
+ if (!class_exists('phpbb_captcha_factory'))
+ {
+ include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
+ }
+
$err = '';
// Make sure user->setup() has been called
@@ -2630,38 +2900,15 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
{
case LOGIN_ERROR_ATTEMPTS:
- // Show confirm image
- $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
- WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_LOGIN;
- $db->sql_query($sql);
-
- // Generate code
- $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
- $confirm_id = md5(unique_id($user->ip));
- $seed = hexdec(substr(unique_id(), 4, 10));
-
- // compute $seed % 0x7fffffff
- $seed -= 0x7fffffff * floor($seed / 0x7fffffff);
-
- $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'confirm_id' => (string) $confirm_id,
- 'session_id' => (string) $user->session_id,
- 'confirm_type' => (int) CONFIRM_LOGIN,
- 'code' => (string) $code,
- 'seed' => (int) $seed)
- );
- $db->sql_query($sql);
+ $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $captcha->init(CONFIRM_LOGIN);
+ // $captcha->reset();
$template->assign_vars(array(
- 'S_CONFIRM_CODE' => true,
- 'CONFIRM_ID' => $confirm_id,
- 'CONFIRM_IMAGE' => '

',
- 'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '
', ''),
+ 'CAPTCHA_TEMPLATE' => $captcha->get_template(),
));
$err = $user->lang[$result['error_msg']];
-
break;
case LOGIN_ERROR_PASSWORD_CONVERT:
@@ -2688,28 +2935,18 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
}
}
- if (!$redirect)
- {
- // We just use what the session code determined...
- // If we are not within the admin directory we use the page dir...
- $redirect = '';
-
- if (!$admin)
- {
- $redirect .= ($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '';
- }
-
- $redirect .= $user->page['page_name'] . (($user->page['query_string']) ? '?' . htmlspecialchars($user->page['query_string']) : '');
- }
-
// Assign credential for username/password pair
$credential = ($admin) ? md5(unique_id()) : false;
$s_hidden_fields = array(
- 'redirect' => $redirect,
'sid' => $user->session_id,
);
+ if ($redirect)
+ {
+ $s_hidden_fields['redirect'] = $redirect;
+ }
+
if ($admin)
{
$s_hidden_fields['credential'] = $credential;
@@ -2722,12 +2959,11 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
'LOGIN_EXPLAIN' => $l_explain,
'U_SEND_PASSWORD' => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '',
- 'U_RESEND_ACTIVATION' => ($config['require_activation'] != USER_ACTIVATION_NONE && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
+ 'U_RESEND_ACTIVATION' => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '',
'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false,
- 'S_LOGIN_ACTION' => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id), // Needs to stay index.$phpEx because we are within the admin directory
'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_ADMIN_AUTH' => $admin,
@@ -2811,7 +3047,7 @@ function login_forum_box($forum_data)
$template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']);
}
- page_header($user->lang['LOGIN']);
+ page_header($user->lang['LOGIN'], false);
$template->assign_vars(array(
'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id'])))
@@ -2933,6 +3169,14 @@ function add_log()
{
global $db, $user;
+ // In phpBB 3.1.x i want to have logging in a class to be able to control it
+ // For now, we need a quite hakish approach to circumvent logging for some actions
+ // @todo implement cleanly
+ if (!empty($GLOBALS['skip_add_log']))
+ {
+ return false;
+ }
+
$args = func_get_args();
$mode = array_shift($args);
@@ -3200,7 +3444,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
// Do not display notices if we suppress them via @
- if (error_reporting() == 0)
+ if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE)
{
return;
}
@@ -3211,6 +3455,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
$msg_text = $msg_long_text;
}
+ if (!defined('E_DEPRECATED'))
+ {
+ define('E_DEPRECATED', 8192);
+ }
+
switch ($errno)
{
case E_NOTICE:
@@ -3243,8 +3492,13 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
// remove complete path to installation, with the risk of changing backslashes meant to be there
$errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile);
$msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text);
-
echo '
[phpBB Debug] PHP Notice: in file
' . $errfile . ' on line
' . $errline . ':
' . $msg_text . '' . "\n";
+
+ // we are writing an image - the user won't see the debug, so let's place it in the log
+ if (defined('IMAGE_OUTPUT') || defined('IN_CRON'))
+ {
+ add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text);
+ }
// echo '
BACKTRACE
' . get_backtrace() . '
' . "\n";
}
@@ -3279,6 +3533,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
}
}
+ if (defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT'))
+ {
+ // let's avoid loops
+ $db->sql_return_on_error(true);
+ add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $msg_text);
+ $db->sql_return_on_error(false);
+ }
+
+ // Do not send 200 OK, but service unavailable on errors
+ header('HTTP/1.1 503 Service Unavailable');
+
garbage_collection();
// Try to not call the adm page data...
@@ -3357,7 +3622,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
}
else
{
- page_header($msg_title);
+ page_header($msg_title, false);
}
}
@@ -3386,6 +3651,11 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
exit_handler();
break;
+
+ // PHP4 compatibility
+ case E_DEPRECATED:
+ return true;
+ break;
}
// If we notice an error not handled here we pass this back to PHP by returning false
@@ -3395,16 +3665,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
/**
* Queries the session table to get information about online guests
-* @param int $forum_id Limits the search to the forum with this id
+* @param int $item_id Limits the search to the item with this id
+* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return int The number of active distinct guest sessions
*/
-function obtain_guest_count($forum_id = 0)
+function obtain_guest_count($item_id = 0, $item = 'forum')
{
global $db, $config;
- if ($forum_id)
+ if ($item_id)
{
- $reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id;
+ $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
}
else
{
@@ -3442,17 +3713,18 @@ function obtain_guest_count($forum_id = 0)
/**
* Queries the session table to get information about online users
-* @param int $forum_id Limits the search to the forum with this id
+* @param int $item_id Limits the search to the item with this id
+* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return array An array containing the ids of online, hidden and visible users, as well as statistical info
*/
-function obtain_users_online($forum_id = 0)
+function obtain_users_online($item_id = 0, $item = 'forum')
{
global $db, $config, $user;
$reading_sql = '';
- if ($forum_id !== 0)
+ if ($item_id !== 0)
{
- $reading_sql = ' AND s.session_forum_id = ' . (int) $forum_id;
+ $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id;
}
$online_users = array(
@@ -3466,7 +3738,7 @@ function obtain_users_online($forum_id = 0)
if ($config['load_online_guests'])
{
- $online_users['guests_online'] = obtain_guest_count($forum_id);
+ $online_users['guests_online'] = obtain_guest_count($item_id, $item);
}
// a little discrete magic to cache this for 30 seconds
@@ -3505,14 +3777,17 @@ function obtain_users_online($forum_id = 0)
/**
* Uses the result of obtain_users_online to generate a localized, readable representation.
* @param mixed $online_users result of obtain_users_online - array with user_id lists for total, hidden and visible users, and statistics
-* @param int $forum_id Indicate that the data is limited to one forum and not global.
+* @param int $item_id Indicate that the data is limited to one item and not global
+* @param string $item The name of the item which is stored in the session table as session_{$item}_id
* @return array An array containing the string for output to the template
*/
-function obtain_users_online_string($online_users, $forum_id = 0)
+function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum')
{
global $config, $db, $user, $auth;
$user_online_link = $online_userlist = '';
+ // Need caps version of $item for language-strings
+ $item_caps = strtoupper($item);
if (sizeof($online_users['online_users']))
{
@@ -3547,18 +3822,18 @@ function obtain_users_online_string($online_users, $forum_id = 0)
$online_userlist = $user->lang['NO_ONLINE_USERS'];
}
- if ($forum_id === 0)
+ if ($item_id === 0)
{
$online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist;
}
else if ($config['load_online_guests'])
{
- $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_FORUM_GUEST'] : $user->lang['BROWSING_FORUM_GUESTS'];
+ $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS'];
$online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']);
}
else
{
- $online_userlist = sprintf($user->lang['BROWSING_FORUM'], $online_userlist);
+ $online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist);
}
// Build online listing
$vars_online = array(
@@ -3612,11 +3887,45 @@ function obtain_users_online_string($online_users, $forum_id = 0)
);
}
+/**
+* Get option bitfield from custom data
+*
+* @param int $bit The bit/value to get
+* @param int $data Current bitfield to check
+* @return bool Returns true if value of constant is set in bitfield, else false
+*/
+function phpbb_optionget($bit, $data)
+{
+ return ($data & 1 << (int) $bit) ? true : false;
+}
+
+/**
+* Set option bitfield
+*
+* @param int $bit The bit/value to set/unset
+* @param bool $set True if option should be set, false if option should be unset.
+* @param int $data Current bitfield to change
+*
+* @return int The new bitfield
+*/
+function phpbb_optionset($bit, $set, $data)
+{
+ if ($set && !($data & 1 << $bit))
+ {
+ $data += 1 << $bit;
+ }
+ else if (!$set && ($data & 1 << $bit))
+ {
+ $data -= 1 << $bit;
+ }
+
+ return $data;
+}
/**
* Generate page header
*/
-function page_header($page_title = '', $display_online_list = true)
+function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{
global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path;
@@ -3656,10 +3965,14 @@ function page_header($page_title = '', $display_online_list = true)
if ($config['load_online'] && $config['load_online_time'] && $display_online_list)
{
- $f = request_var('f', 0);
- $f = max($f, 0);
- $online_users = obtain_users_online($f);
- $user_online_strings = obtain_users_online_string($online_users, $f);
+ /**
+ * Load online data:
+ * For obtaining another session column use $item and $item_id in the function-parameter, whereby the column is session_{$item}_id.
+ */
+ $item_id = max($item_id, 0);
+
+ $online_users = obtain_users_online($item_id, $item);
+ $user_online_strings = obtain_users_online_string($online_users, $item_id, $item);
$l_online_users = $user_online_strings['l_online_users'];
$online_userlist = $user_online_strings['online_userlist'];
@@ -3731,6 +4044,26 @@ function page_header($page_title = '', $display_online_list = true)
$user_lang = substr($user_lang, 0, strpos($user_lang, '-x-'));
}
+ $forum_id = request_var('f', 0);
+ $topic_id = request_var('t', 0);
+
+ $s_feed_news = false;
+
+ // Get option for news
+ if ($config['feed_enable'])
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $db->sql_query_limit($sql, 1, 0, 600);
+ $s_feed_news = (int) $db->sql_fetchfield('forum_id');
+ $db->sql_freeresult($result);
+ }
+
+ // Determine board url - we may need it later
+ $board_url = generate_board_url() . '/';
+ $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path;
+
// The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array(
'SITENAME' => $config['sitename'],
@@ -3748,11 +4081,13 @@ function page_header($page_title = '', $display_online_list = true)
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
+ 'S_USER_NEW' => $user->data['user_new'],
'SID' => $SID,
'_SID' => $_SID,
'SESSION_ID' => $user->session_id,
'ROOT_PATH' => $phpbb_root_path,
+ 'BOARD_URL' => $board_url,
'L_LOGIN_LOGOUT' => $l_login_logout,
'L_INDEX' => $user->lang['FORUM_INDEX'],
@@ -3774,10 +4109,14 @@ function page_header($page_title = '', $display_online_list = true)
'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'),
'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'),
'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'),
+ 'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'),
'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'),
'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'),
'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'),
+ 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
+ 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '',
+ 'U_FEED' => generate_board_url() . "/feed.$phpEx",
'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false,
'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false,
@@ -3799,22 +4138,44 @@ function page_header($page_title = '', $display_online_list = true)
'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0,
'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0,
'S_REGISTER_ENABLED' => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false,
+ 'S_FORUM_ID' => $forum_id,
+ 'S_TOPIC_ID' => $topic_id,
- 'T_THEME_PATH' => "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme',
- 'T_TEMPLATE_PATH' => "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template',
- 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$phpbb_root_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$phpbb_root_path}styles/" . $user->theme['template_path'] . '/template',
- 'T_IMAGESET_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset',
- 'T_IMAGESET_LANG_PATH' => "{$phpbb_root_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'],
- 'T_IMAGES_PATH' => "{$phpbb_root_path}images/",
- 'T_SMILIES_PATH' => "{$phpbb_root_path}{$config['smilies_path']}/",
- 'T_AVATAR_PATH' => "{$phpbb_root_path}{$config['avatar_path']}/",
- 'T_AVATAR_GALLERY_PATH' => "{$phpbb_root_path}{$config['avatar_gallery_path']}/",
- 'T_ICONS_PATH' => "{$phpbb_root_path}{$config['icons_path']}/",
- 'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/",
- 'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/",
- 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&id=" . $user->theme['style_id'] . '&lang=' . $user->data['user_lang'],
+ 'S_LOGIN_ACTION' => (!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') . '&redirect=' . urlencode(str_replace('&', '&', build_url())) : append_sid("index.$phpEx", false, true, $user->session_id) . '&redirect=' . urlencode(str_replace('&', '&', build_url())),
+
+ 'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false,
+ 'S_ENABLE_FEEDS_FORUMS' => ($config['feed_overall_forums']) ? true : false,
+ 'S_ENABLE_FEEDS_TOPICS' => ($config['feed_overall_topics']) ? true : false,
+ 'S_ENABLE_FEEDS_NEWS' => ($s_feed_news) ? true : false,
+
+ 'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme',
+ 'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template',
+ 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$web_path}styles/" . $user->theme['template_path'] . '/template',
+ 'T_IMAGESET_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset',
+ 'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'],
+ 'T_IMAGES_PATH' => "{$web_path}images/",
+ 'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/",
+ 'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/",
+ 'T_AVATAR_GALLERY_PATH' => "{$web_path}{$config['avatar_gallery_path']}/",
+ 'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/",
+ 'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
+ 'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
+ 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&lang=' . $user->data['user_lang']),
'T_STYLESHEET_NAME' => $user->theme['theme_name'],
+ 'T_THEME_NAME' => $user->theme['theme_path'],
+ 'T_TEMPLATE_NAME' => $user->theme['template_path'],
+ 'T_SUPER_TEMPLATE_NAME' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path'],
+ 'T_IMAGESET_NAME' => $user->theme['imageset_path'],
+ 'T_IMAGESET_LANG_NAME' => $user->data['user_lang'],
+ 'T_IMAGES' => 'images',
+ 'T_SMILIES' => $config['smilies_path'],
+ 'T_AVATAR' => $config['avatar_path'],
+ 'T_AVATAR_GALLERY' => $config['avatar_gallery_path'],
+ 'T_ICONS' => $config['icons_path'],
+ 'T_RANKS' => $config['ranks_path'],
+ 'T_UPLOAD' => $config['upload_path'],
+
'SITE_LOGO_IMG' => $user->img('site_logo'),
'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')),
@@ -3848,7 +4209,7 @@ function page_footer($run_cron = true)
$db->sql_report('display');
}
- $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
+ $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
if ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))
{
@@ -3876,35 +4237,55 @@ function page_footer($run_cron = true)
);
// Call cron-type script
+ $call_cron = false;
if (!defined('IN_CRON') && $run_cron && !$config['board_disable'])
+ {
+ $call_cron = true;
+ $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time();
+
+ // Any old lock present?
+ if (!empty($config['cron_lock']))
+ {
+ $cron_time = explode(' ', $config['cron_lock']);
+
+ // If 1 hour lock is present we do not call cron.php
+ if ($cron_time[0] + 3600 >= $time_now)
+ {
+ $call_cron = false;
+ }
+ }
+ }
+
+ // Call cron job?
+ if ($call_cron)
{
$cron_type = '';
- if (time() - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
+ if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx))
{
// Process email queue
$cron_type = 'queue';
}
- else if (method_exists($cache, 'tidy') && time() - $config['cache_gc'] > $config['cache_last_gc'])
+ else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc'])
{
// Tidy the cache
$cron_type = 'tidy_cache';
}
- else if (time() - $config['warnings_gc'] > $config['warnings_last_gc'])
+ else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc']))
{
$cron_type = 'tidy_warnings';
}
- else if (time() - $config['database_gc'] > $config['database_last_gc'])
+ else if ($time_now - $config['database_gc'] > $config['database_last_gc'])
{
// Tidy the database
$cron_type = 'tidy_database';
}
- else if (time() - $config['search_gc'] > $config['search_last_gc'])
+ else if ($time_now - $config['search_gc'] > $config['search_last_gc'])
{
// Tidy the search
$cron_type = 'tidy_search';
}
- else if (time() - $config['session_gc'] > $config['session_last_gc'])
+ else if ($time_now - $config['session_gc'] > $config['session_last_gc'])
{
$cron_type = 'tidy_sessions';
}
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 79282c0358..d42a81fa35 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -17,95 +17,47 @@ if (!defined('IN_PHPBB'))
}
/**
-* Recalculate Binary Tree
-function recalc_btree($sql_id, $sql_table, $module_class = '')
+* Recalculate Nested Sets
+*
+* @param int $new_id first left_id (should start with 1)
+* @param string $pkey primary key-column (containing the id for the parent_id of the children)
+* @param string $table constant or fullname of the table
+* @param int $parent_id parent_id of the current set (default = 0)
+* @param array $where contains strings to compare closer on the where statement (additional)
+*
+* @author EXreaction
+*/
+function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = array())
{
global $db;
- if (!$sql_id || !$sql_table)
- {
- return;
- }
-
- $sql_where = ($module_class) ? " WHERE module_class = '" . $db->sql_escape($module_class) . "'" : '';
-
- // Reset to minimum possible left and right id
- $sql = "SELECT MIN(left_id) as min_left_id, MIN(right_id) as min_right_id
- FROM $sql_table
- $sql_where";
+ $sql = 'SELECT *
+ FROM ' . $table . '
+ WHERE parent_id = ' . (int) $parent_id .
+ ((!empty($where)) ? ' AND ' . implode(' AND ', $where) : '') . '
+ ORDER BY left_id ASC';
$result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ // First we update the left_id for this module
+ if ($row['left_id'] != $new_id)
+ {
+ $db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('left_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}");
+ }
+ $new_id++;
+
+ // Then we go through any children and update their left/right id's
+ recalc_nested_sets($new_id, $pkey, $table, $row[$pkey], $where);
+
+ // Then we come back and update the right_id for this module
+ if ($row['right_id'] != $new_id)
+ {
+ $db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('right_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}");
+ }
+ $new_id++;
+ }
$db->sql_freeresult($result);
-
- $substract = (int) (min($row['min_left_id'], $row['min_right_id']) - 1);
-
- if ($substract > 0)
- {
- $sql = "UPDATE $sql_table
- SET left_id = left_id - $substract, right_id = right_id - $substract
- $sql_where";
- $db->sql_query($sql);
- }
-
- $sql = "SELECT $sql_id, parent_id, left_id, right_id
- FROM $sql_table
- $sql_where
- ORDER BY left_id ASC, parent_id ASC, $sql_id ASC";
- $f_result = $db->sql_query($sql);
-
- while ($item_data = $db->sql_fetchrow($f_result))
- {
- if ($item_data['parent_id'])
- {
- $sql = "SELECT left_id, right_id
- FROM $sql_table
- $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
- $sql_id = {$item_data['parent_id']}";
- $result = $db->sql_query($sql);
-
- if (!$row = $db->sql_fetchrow($result))
- {
- $sql = "UPDATE $sql_table SET parent_id = 0 WHERE $sql_id = " . $item_data[$sql_id];
- $db->sql_query($sql);
- }
- $db->sql_freeresult($result);
-
- $sql = "UPDATE $sql_table
- SET left_id = left_id + 2, right_id = right_id + 2
- $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
- left_id > {$row['right_id']}";
- $db->sql_query($sql);
-
- $sql = "UPDATE $sql_table
- SET right_id = right_id + 2
- $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
- {$row['left_id']} BETWEEN left_id AND right_id";
- $db->sql_query($sql);
-
- $item_data['left_id'] = $row['right_id'];
- $item_data['right_id'] = $row['right_id'] + 1;
- }
- else
- {
- $sql = "SELECT MAX(right_id) AS right_id
- FROM $sql_table
- $sql_where";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $item_data['left_id'] = $row['right_id'] + 1;
- $item_data['right_id'] = $row['right_id'] + 2;
- }
-
- $sql = "UPDATE $sql_table
- SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']}
- WHERE $sql_id = " . $item_data[$sql_id];
- $db->sql_query($sql);
- }
- $db->sql_freeresult($f_result);
}
-*/
/**
* Simple version of jumpbox, just lists authed forums
@@ -117,7 +69,7 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl =
$acl = ($ignore_acl) ? '' : (($only_acl_post) ? 'f_post' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel'));
// This query is identical to the jumpbox one
- $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
+ $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id
FROM ' . FORUMS_TABLE . '
ORDER BY left_id ASC';
$result = $db->sql_query($sql, 600);
@@ -354,12 +306,157 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl
return $rows;
}
+/**
+* Copies permissions from one forum to others
+*
+* @param int $src_forum_id The source forum we want to copy permissions from
+* @param array $dest_forum_ids The destination forum(s) we want to copy to
+* @param bool $clear_dest_perms True if destination permissions should be deleted
+* @param bool $add_log True if log entry should be added
+*
+* @return bool False on error
+*
+* @author bantu
+*/
+function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true)
+{
+ global $db;
+
+ // Only one forum id specified
+ if (!is_array($dest_forum_ids))
+ {
+ $dest_forum_ids = array($dest_forum_ids);
+ }
+
+ // Make sure forum ids are integers
+ $src_forum_id = (int) $src_forum_id;
+ $dest_forum_ids = array_map('intval', $dest_forum_ids);
+
+ // No source forum or no destination forums specified
+ if (empty($src_forum_id) || empty($dest_forum_ids))
+ {
+ return false;
+ }
+
+ // Check if source forum exists
+ $sql = 'SELECT forum_name
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $src_forum_id;
+ $result = $db->sql_query($sql);
+ $src_forum_name = $db->sql_fetchfield('forum_name');
+ $db->sql_freeresult($result);
+
+ // Source forum doesn't exist
+ if (empty($src_forum_name))
+ {
+ return false;
+ }
+
+ // Check if destination forums exists
+ $sql = 'SELECT forum_id, forum_name
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
+ $result = $db->sql_query($sql);
+
+ $dest_forum_ids = $dest_forum_names = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $dest_forum_ids[] = (int) $row['forum_id'];
+ $dest_forum_names[] = $row['forum_name'];
+ }
+ $db->sql_freeresult($result);
+
+ // No destination forum exists
+ if (empty($dest_forum_ids))
+ {
+ return false;
+ }
+
+ // From the mysql documentation:
+ // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear
+ // in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
+ // Due to this we stay on the safe side if we do the insertion "the manual way"
+
+ // Rowsets we're going to insert
+ $users_sql_ary = $groups_sql_ary = array();
+
+ // Query acl users table for source forum data
+ $sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting
+ FROM ' . ACL_USERS_TABLE . '
+ WHERE forum_id = ' . $src_forum_id;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $row = array(
+ 'user_id' => (int) $row['user_id'],
+ 'auth_option_id' => (int) $row['auth_option_id'],
+ 'auth_role_id' => (int) $row['auth_role_id'],
+ 'auth_setting' => (int) $row['auth_setting'],
+ );
+
+ foreach ($dest_forum_ids as $dest_forum_id)
+ {
+ $users_sql_ary[] = $row + array('forum_id' => $dest_forum_id);
+ }
+ }
+ $db->sql_freeresult($result);
+
+ // Query acl groups table for source forum data
+ $sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting
+ FROM ' . ACL_GROUPS_TABLE . '
+ WHERE forum_id = ' . $src_forum_id;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $row = array(
+ 'group_id' => (int) $row['group_id'],
+ 'auth_option_id' => (int) $row['auth_option_id'],
+ 'auth_role_id' => (int) $row['auth_role_id'],
+ 'auth_setting' => (int) $row['auth_setting'],
+ );
+
+ foreach ($dest_forum_ids as $dest_forum_id)
+ {
+ $groups_sql_ary[] = $row + array('forum_id' => $dest_forum_id);
+ }
+ }
+ $db->sql_freeresult($result);
+
+ $db->sql_transaction('begin');
+
+ // Clear current permissions of destination forums
+ if ($clear_dest_perms)
+ {
+ $sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
+ $db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids);
+ $db->sql_query($sql);
+ }
+
+ $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
+ $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
+
+ if ($add_log)
+ {
+ add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names));
+ }
+
+ $db->sql_transaction('commit');
+
+ return true;
+}
+
/**
* Get physical file listing
*/
function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')
{
- $matches = array();
+ $matches = array($dir => array());
// Remove initial / if present
$rootdir = (substr($rootdir, 0, 1) == '/') ? substr($rootdir, 1) : $rootdir;
@@ -940,19 +1037,61 @@ function delete_attachments($mode, $ids, $resync = true)
// Update post indicators for posts now no longer having attachments
if (sizeof($post_ids))
{
- $sql = 'UPDATE ' . POSTS_TABLE . '
- SET post_attachment = 0
- WHERE ' . $db->sql_in_set('post_id', $post_ids);
- $db->sql_query($sql);
+ // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table
+ $sql = 'SELECT post_msg_id
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
+ AND in_message = 0
+ AND is_orphan = 0';
+ $result = $db->sql_query($sql);
+
+ $remaining_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $remaining_ids[] = $row['post_msg_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // Now only unset those ids remaining
+ $post_ids = array_diff($post_ids, $remaining_ids);
+
+ if (sizeof($post_ids))
+ {
+ $sql = 'UPDATE ' . POSTS_TABLE . '
+ SET post_attachment = 0
+ WHERE ' . $db->sql_in_set('post_id', $post_ids);
+ $db->sql_query($sql);
+ }
}
// Update message table if messages are affected
if (sizeof($message_ids))
{
- $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
- SET message_attachment = 0
- WHERE ' . $db->sql_in_set('msg_id', $message_ids);
- $db->sql_query($sql);
+ // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table
+ $sql = 'SELECT post_msg_id
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . '
+ AND in_message = 1
+ AND is_orphan = 0';
+ $result = $db->sql_query($sql);
+
+ $remaining_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $remaining_ids[] = $row['post_msg_id'];
+ }
+ $db->sql_freeresult($result);
+
+ // Now only unset those ids remaining
+ $message_ids = array_diff($message_ids, $remaining_ids);
+
+ if (sizeof($message_ids))
+ {
+ $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
+ SET message_attachment = 0
+ WHERE ' . $db->sql_in_set('msg_id', $message_ids);
+ $db->sql_query($sql);
+ }
}
// Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
@@ -1098,7 +1237,7 @@ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
// Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
$sql = 'SELECT COUNT(attach_id) AS num_entries
FROM ' . ATTACHMENTS_TABLE . "
- WHERE physical_filename = '" . $db->sql_escape(basename($filename)) . "'";
+ WHERE physical_filename = '" . $db->sql_escape(utf8_basename($filename)) . "'";
$result = $db->sql_query($sql);
$num_entries = (int) $db->sql_fetchfield('num_entries');
$db->sql_freeresult($result);
@@ -1109,7 +1248,7 @@ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
return false;
}
- $filename = ($mode == 'thumbnail') ? 'thumb_' . basename($filename) : basename($filename);
+ $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename);
return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename);
}
@@ -1193,6 +1332,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
switch ($mode)
{
case 'topic_moved':
+ $db->sql_transaction('begin');
switch ($db->sql_layer)
{
case 'mysql4':
@@ -1229,9 +1369,13 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
break;
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'topic_approved':
+
+ $db->sql_transaction('begin');
switch ($db->sql_layer)
{
case 'mysql4':
@@ -1267,11 +1411,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$db->sql_query($sql);
break;
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'post_reported':
$post_ids = $post_reported = array();
+ $db->sql_transaction('begin');
+
$sql = 'SELECT p.post_id, p.post_reported
FROM ' . POSTS_TABLE . " p
$where_sql
@@ -1322,7 +1470,9 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'topic_reported':
if ($sync_extra)
@@ -1332,6 +1482,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_ids = $topic_reported = array();
+ $db->sql_transaction('begin');
+
$sql = 'SELECT DISTINCT(t.topic_id)
FROM ' . POSTS_TABLE . " t
$where_sql_and t.post_reported = 1";
@@ -1364,11 +1516,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
$db->sql_query($sql);
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'post_attachment':
$post_ids = $post_attachment = array();
+ $db->sql_transaction('begin');
+
$sql = 'SELECT p.post_id, p.post_attachment
FROM ' . POSTS_TABLE . " p
$where_sql
@@ -1419,7 +1575,9 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'topic_attachment':
if ($sync_extra)
@@ -1429,6 +1587,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_ids = $topic_attachment = array();
+ $db->sql_transaction('begin');
+
$sql = 'SELECT DISTINCT(t.topic_id)
FROM ' . POSTS_TABLE . " t
$where_sql_and t.post_attachment = 1";
@@ -1461,10 +1621,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
$db->sql_query($sql);
}
- break;
+
+ $db->sql_transaction('commit');
+
+ break;
case 'forum':
+ $db->sql_transaction('begin');
+
// 1: Get the list of all forums
$sql = 'SELECT f.*
FROM ' . FORUMS_TABLE . " f
@@ -1665,11 +1830,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$db->sql_query($sql);
}
}
- break;
+
+ $db->sql_transaction('commit');
+ break;
case 'topic':
$topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array();
+ $db->sql_transaction('begin');
+
$sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time
FROM ' . TOPICS_TABLE . " t
$where_sql";
@@ -1992,6 +2161,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
}
unset($topic_data);
+ $db->sql_transaction('commit');
+
// if some topics have been resync'ed then resync parent forums
// except when we're only syncing a range, we don't want to sync forums during
// batch processing.
@@ -1999,7 +2170,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
{
sync('forum', 'forum_id', array_values($resync_forums), true, true);
}
- break;
+ break;
}
return;
@@ -2185,12 +2356,13 @@ function cache_moderators()
// Remove users who have group memberships with DENY moderator permissions
$sql = $db->sql_build_query('SELECT', array(
- 'SELECT' => 'a.forum_id, ug.user_id',
+ 'SELECT' => 'a.forum_id, ug.user_id, g.group_id',
'FROM' => array(
ACL_OPTIONS_TABLE => 'o',
USER_GROUP_TABLE => 'ug',
- ACL_GROUPS_TABLE => 'a'
+ ACL_GROUPS_TABLE => 'a',
+ GROUPS_TABLE => 'g',
),
'LEFT_JOIN' => array(
@@ -2204,6 +2376,8 @@ function cache_moderators()
AND ((a.auth_setting = ' . ACL_NEVER . ' AND r.auth_setting IS NULL)
OR r.auth_setting = ' . ACL_NEVER . ')
AND a.group_id = ug.group_id
+ AND g.group_id = ug.group_id
+ AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)
AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "
AND ug.user_pending = 0
AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char),
@@ -2323,7 +2497,7 @@ function cache_moderators()
/**
* View log
*/
-function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC')
+function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC', $keywords = '')
{
global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path;
@@ -2343,15 +2517,15 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
if ($topic_id)
{
- $sql_forum = 'AND l.topic_id = ' . intval($topic_id);
+ $sql_forum = 'AND l.topic_id = ' . (int) $topic_id;
}
else if (is_array($forum_id))
{
$sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id));
}
- else
+ else if ($forum_id)
{
- $sql_forum = ($forum_id) ? 'AND l.forum_id = ' . intval($forum_id) : '';
+ $sql_forum = 'AND l.forum_id = ' . (int) $forum_id;
}
break;
@@ -2374,11 +2548,40 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
return;
}
+ $keywords = preg_split('#[\s+\-|*()]+#u', utf8_strtolower(preg_quote($keywords, '#')), 0, PREG_SPLIT_NO_EMPTY);
+ $sql_keywords = '';
+
+ if (!empty($keywords))
+ {
+ $keywords_pattern = '#' . implode('|', $keywords) . '#ui';
+ for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++)
+ {
+ $keywords[$i] = $db->sql_like_expression($db->any_char . $keywords[$i] . $db->any_char);
+ }
+
+ $operations = array();
+ foreach ($user->lang as $key => $value)
+ {
+ if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value))
+ {
+ $operations[] = $key;
+ }
+ }
+
+ $sql_keywords = 'AND (';
+ if (!empty($operations))
+ {
+ $sql_keywords .= $db->sql_in_set('l.log_operation', $operations) . ' OR ';
+ }
+ $sql_keywords .= 'LOWER(l.log_data) ' . implode(' OR LOWER(l.log_data) ', $keywords) . ')';
+ }
+
$sql = "SELECT l.*, u.username, u.username_clean, u.user_colour
FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u
WHERE l.log_type = $log_type
AND u.user_id = l.user_id
" . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . "
+ $sql_keywords
$sql_forum
ORDER BY $sort_by";
$result = $db->sql_query_limit($sql, $limit, $offset);
@@ -2419,7 +2622,8 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
if (!empty($row['log_data']))
{
- $log_data_ary = unserialize($row['log_data']);
+ $log_data_ary = @unserialize($row['log_data']);
+ $log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary;
if (isset($user->lang[$row['log_operation']]))
{
@@ -2442,7 +2646,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
$log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action']));
}
}
- else
+ else if (!empty($log_data_ary))
{
$log[$i]['action'] .= '
' . implode('', $log_data_ary);
}
@@ -2540,9 +2744,11 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
}
$sql = 'SELECT COUNT(l.log_id) AS total_entries
- FROM ' . LOG_TABLE . " l
+ FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u
WHERE l.log_type = $log_type
+ AND l.user_id = u.user_id
AND l.log_time >= $limit_days
+ $sql_keywords
$sql_forum";
$result = $db->sql_query($sql);
$log_count = (int) $db->sql_fetchfield('total_entries');
@@ -2685,7 +2891,7 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li
$offset = ($offset - $limit < 0) ? 0 : $offset - $limit;
}
- $sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason
+ $sql = 'SELECT *
FROM ' . USERS_TABLE . '
WHERE user_type = ' . USER_INACTIVE .
(($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . "
@@ -3054,4 +3260,43 @@ function add_permission_language()
return true;
}
+/**
+ * Obtains the latest version information
+ *
+ * @param bool $force_update Ignores cached data. Defaults to false.
+ * @param bool $warn_fail Trigger a warning if obtaining the latest version information fails. Defaults to false.
+ * @param int $ttl Cache version information for $ttl seconds. Defaults to 86400 (24 hours).
+ *
+ * @return string | false Version info on success, false on failure.
+ */
+function obtain_latest_version_info($force_update = false, $warn_fail = false, $ttl = 86400)
+{
+ global $cache;
+
+ $info = $cache->get('versioncheck');
+
+ if ($info === false || $force_update)
+ {
+ $errstr = '';
+ $errno = 0;
+
+ $info = get_remote_file('www.phpbb.com', '/updatecheck',
+ ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
+
+ if ($info === false)
+ {
+ $cache->destroy('versioncheck');
+ if ($warn_fail)
+ {
+ trigger_error($errstr, E_USER_WARNING);
+ }
+ return false;
+ }
+
+ $cache->put('versioncheck', $info, $ttl);
+ }
+
+ return $info;
+}
+
?>
\ No newline at end of file
diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php
index 881e1ba5cc..590daabf1d 100644
--- a/phpBB/includes/functions_compress.php
+++ b/phpBB/includes/functions_compress.php
@@ -155,7 +155,12 @@ class compress_zip extends compress
*/
function compress_zip($mode, $file)
{
- return $this->fp = @fopen($file, $mode . 'b');
+ $this->fp = @fopen($file, $mode . 'b');
+
+ if (!$this->fp)
+ {
+ trigger_error('Unable to open file ' . $file . ' [' . $mode . 'b]');
+ }
}
/**
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index 3107177137..c265d0ae41 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -250,6 +250,11 @@ function get_context($text, $words, $length = 400)
// first replace all whitespaces with single spaces
$text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", ' '));
+ // we need to turn the entities back into their original form, to not cut the message in between them
+ $entities = array('<', '>', '[', ']', '.', ':', ':');
+ $characters = array('<', '>', '[', ']', '.', ':', ':');
+ $text = str_replace($entities, $characters, $text);
+
$word_indizes = array();
if (sizeof($words))
{
@@ -345,13 +350,13 @@ function get_context($text, $words, $length = 400)
}
}
}
- return $final_text;
+ return str_replace($characters, $entities, $final_text);
}
}
if (!sizeof($words) || !sizeof($word_indizes))
{
- return (utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text;
+ return str_replace($characters, $entities, ((utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text));
}
}
@@ -680,6 +685,12 @@ function censor_text($text)
{
static $censors;
+ // Nothing to do?
+ if ($text === '')
+ {
+ return '';
+ }
+
// We moved the word censor checks in here because we call this function quite often - and then only need to do the check once
if (!isset($censors) || !is_array($censors))
{
@@ -728,7 +739,8 @@ function smiley_text($text, $force_option = false)
}
else
{
- return preg_replace('#
 \/><!\-\- s\1 \-\->#', '<img src=)
', $text);
+ $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
+ return preg_replace('#
 \/><!\-\- s\1 \-\->#', '<img src=)
', $text);
}
}
@@ -836,8 +848,8 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
// Some basics...
$attachment['extension'] = strtolower(trim($attachment['extension']));
- $filename = $phpbb_root_path . $config['upload_path'] . '/' . basename($attachment['physical_filename']);
- $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . basename($attachment['physical_filename']);
+ $filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']);
+ $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']);
$upload_icon = '';
@@ -853,17 +865,15 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
}
}
- $filesize = $attachment['filesize'];
- $size_lang = ($filesize >= 1048576) ? $user->lang['MIB'] : (($filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES']);
- $filesize = get_formatted_filesize($filesize, false);
+ $filesize = get_formatted_filesize($attachment['filesize'], false);
$comment = bbcode_nl2br(censor_text($attachment['attach_comment']));
$block_array += array(
'UPLOAD_ICON' => $upload_icon,
- 'FILESIZE' => $filesize,
- 'SIZE_LANG' => $size_lang,
- 'DOWNLOAD_NAME' => basename($attachment['real_filename']),
+ 'FILESIZE' => $filesize['value'],
+ 'SIZE_LANG' => $filesize['unit'],
+ 'DOWNLOAD_NAME' => utf8_basename($attachment['real_filename']),
'COMMENT' => $comment,
);
diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php
index 2213df7d0f..82ec114c09 100644
--- a/phpBB/includes/functions_convert.php
+++ b/phpBB/includes/functions_convert.php
@@ -551,7 +551,7 @@ function _import_check($config_var, $source, $use_target)
);
// copy file will prepend $phpBB_root_path
- $target = $config[$config_var] . '/' . basename(($use_target === false) ? $source : $use_target);
+ $target = $config[$config_var] . '/' . utf8_basename(($use_target === false) ? $source : $use_target);
if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0)
{
@@ -567,11 +567,11 @@ function _import_check($config_var, $source, $use_target)
if ($result['copied'])
{
- $result['target'] = basename($target);
+ $result['target'] = utf8_basename($target);
}
else
{
- $result['target'] = ($use_target !== false) ? $result['orig_source'] : basename($target);
+ $result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target);
}
return $result;
@@ -600,7 +600,7 @@ function import_attachment($source, $use_target = false)
{
$thumb_dir = $convert->convertor['thumbnails'][0];
$thumb_prefix = $convert->convertor['thumbnails'][1];
- $thumb_source = $thumb_dir . $thumb_prefix . basename($result['source']);
+ $thumb_source = $thumb_dir . $thumb_prefix . utf8_basename($result['source']);
if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0)
{
@@ -1698,7 +1698,8 @@ function add_default_groups()
'REGISTERED_COPPA' => array('', 0, 0),
'GLOBAL_MODERATORS' => array('00AA00', 1, 0),
'ADMINISTRATORS' => array('AA0000', 1, 1),
- 'BOTS' => array('9E8DA7', 0, 0)
+ 'BOTS' => array('9E8DA7', 0, 0),
+ 'NEWLY_REGISTERED' => array('', 0, 0),
);
$sql = 'SELECT *
@@ -2256,7 +2257,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour
if (substr($trg, -1) == '/')
{
- $trg .= basename($src);
+ $trg .= utf8_basename($src);
}
$src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
$trg_path = $trg;
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index fdcc118269..cec1becb6e 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -102,6 +102,19 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_tracking_info = array();
$branch_root_id = $root_data['forum_id'];
+
+ // Check for unread global announcements (index page only)
+ $ga_unread = false;
+ if ($root_data['forum_id'] == 0)
+ {
+ $unread_ga_list = get_unread_topics($user->data['user_id'], 'AND t.forum_id = 0', '', 1);
+
+ if (!empty($unread_ga_list))
+ {
+ $ga_unread = true;
+ }
+ }
+
while ($row = $db->sql_fetchrow($result))
{
$forum_id = $row['forum_id'];
@@ -154,6 +167,8 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_tracking_info[$forum_id] = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark'];
}
+ // Count the difference of real to public topics, so we can display an information to moderators
+ $row['forum_id_unapproved_topics'] = ($auth->acl_get('m_approve', $forum_id) && ($row['forum_topics_real'] != $row['forum_topics'])) ? $forum_id : 0;
$row['forum_topics'] = ($auth->acl_get('m_approve', $forum_id)) ? $row['forum_topics_real'] : $row['forum_topics'];
// Display active topics from this forum?
@@ -212,6 +227,11 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$subforums[$parent_id][$row['parent_id']]['children'][] = $forum_id;
}
+ if (!$forum_rows[$parent_id]['forum_id_unapproved_topics'] && $row['forum_id_unapproved_topics'])
+ {
+ $forum_rows[$parent_id]['forum_id_unapproved_topics'] = $forum_id;
+ }
+
$forum_rows[$parent_id]['forum_topics'] += $row['forum_topics'];
// Do not list redirects in LINK Forums as Posts.
@@ -248,6 +268,8 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
}
else
{
+ // Add 0 to forums array to mark global announcements correctly
+ $forum_ids[] = 0;
markread('topics', $forum_ids);
$message = sprintf($user->lang['RETURN_FORUM'], '
', '');
}
@@ -300,6 +322,12 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_unread = (isset($forum_tracking_info[$forum_id]) && $row['orig_forum_last_post_time'] > $forum_tracking_info[$forum_id]) ? true : false;
+ // Mark the first visible forum on index as unread if there's any unread global announcement
+ if (($forum_id == $forum_ids_moderator[0]) && ($root_data['forum_id'] == 0) && $ga_unread)
+ {
+ $forum_unread = true;
+ }
+
$folder_image = $folder_alt = $l_subforums = '';
$subforums_list = array();
@@ -428,6 +456,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false,
'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false,
'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false,
+ 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options'])) ? true : false,
'FORUM_ID' => $row['forum_id'],
'FORUM_NAME' => $row['forum_name'],
@@ -451,6 +480,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'L_FORUM_FOLDER_ALT' => $folder_alt,
'L_MODERATOR_STR' => $l_moderator,
+ 'U_UNAPPROVED_TOPICS' => ($row['forum_id_unapproved_topics']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=unapproved_topics&f=' . $row['forum_id_unapproved_topics']) : '',
'U_VIEWFORUM' => $u_viewforum,
'U_LAST_POSTER' => get_username_string('profile', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']),
'U_LAST_POST' => $last_post_url)
@@ -473,8 +503,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums') : '',
'S_HAS_SUBFORUM' => ($visible_forums) ? true : false,
'L_SUBFORUM' => ($visible_forums == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS'],
- 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'))
- );
+ 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
+ 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPICS_UNAPPROVED'),
+ ));
if ($return_moderators)
{
@@ -514,7 +545,7 @@ function generate_forum_rules(&$forum_data)
*/
function generate_forum_nav(&$forum_data)
{
- global $db, $user, $template, $auth;
+ global $db, $user, $template, $auth, $config;
global $phpEx, $phpbb_root_path;
if (!$auth->acl_get('f_list', $forum_data['forum_id']))
@@ -561,8 +592,10 @@ function generate_forum_nav(&$forum_data)
$template->assign_vars(array(
'FORUM_ID' => $forum_data['forum_id'],
'FORUM_NAME' => $forum_data['forum_name'],
- 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']))
- );
+ 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']),
+
+ 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false,
+ ));
return;
}
@@ -658,14 +691,7 @@ function get_moderators(&$forum_moderators, $forum_id = false)
{
global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth;
- // Have we disabled the display of moderators? If so, then return
- // from whence we came ...
- if (!$config['load_moderators'])
- {
- return;
- }
-
- $forum_sql = '';
+ $forum_id_ary = array();
if ($forum_id !== false)
{
@@ -674,13 +700,8 @@ function get_moderators(&$forum_moderators, $forum_id = false)
$forum_id = array($forum_id);
}
- // If we don't have a forum then we can't have a moderator
- if (!sizeof($forum_id))
- {
- return;
- }
-
- $forum_sql = 'AND m.' . $db->sql_in_set('forum_id', $forum_id);
+ // Exchange key/value pair to be able to faster check for the forum id existence
+ $forum_id_ary = array_flip($forum_id);
}
$sql_array = array(
@@ -701,17 +722,25 @@ function get_moderators(&$forum_moderators, $forum_id = false)
),
),
- 'WHERE' => "m.display_on_index = 1 $forum_sql",
+ 'WHERE' => 'm.display_on_index = 1',
);
+ // We query every forum here because for caching we should not have any parameter.
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query($sql, 3600);
while ($row = $db->sql_fetchrow($result))
{
+ $f_id = (int) $row['forum_id'];
+
+ if (!isset($forum_id_ary[$f_id]))
+ {
+ continue;
+ }
+
if (!empty($row['user_id']))
{
- $forum_moderators[$row['forum_id']][] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
+ $forum_moderators[$f_id][] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
}
else
{
@@ -719,11 +748,11 @@ function get_moderators(&$forum_moderators, $forum_id = false)
if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile'))
{
- $forum_moderators[$row['forum_id']][] = '
' . $group_name . '';
+ $forum_moderators[$f_id][] = '
' . $group_name . '';
}
else
{
- $forum_moderators[$row['forum_id']][] = '
' . $group_name . '';
+ $forum_moderators[$f_id][] = '
' . $group_name . '';
}
}
}
@@ -1200,14 +1229,15 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank
* @param string $avatar_width Width of users avatar
* @param string $avatar_height Height of users avatar
* @param string $alt Optional language string for alt tag within image, can be a language key or text
+* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP
*
* @return string Avatar image
*/
-function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR')
+function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false)
{
global $user, $config, $phpbb_root_path, $phpEx;
- if (empty($avatar) || !$avatar_type)
+ if (empty($avatar) || !$avatar_type || (!$config['allow_avatar'] && !$ignore_config))
{
return '';
}
@@ -1217,12 +1247,27 @@ function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $
switch ($avatar_type)
{
case AVATAR_UPLOAD:
+ if (!$config['allow_avatar_upload'] && !$ignore_config)
+ {
+ return '';
+ }
$avatar_img = $phpbb_root_path . "download/file.$phpEx?avatar=";
break;
case AVATAR_GALLERY:
+ if (!$config['allow_avatar_local'] && !$ignore_config)
+ {
+ return '';
+ }
$avatar_img = $phpbb_root_path . $config['avatar_gallery_path'] . '/';
break;
+
+ case AVATAR_REMOTE:
+ if (!$config['allow_avatar_remote'] && !$ignore_config)
+ {
+ return '';
+ }
+ break;
}
$avatar_img .= $avatar;
diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php
index 611b0a7bc3..a5889224a1 100644
--- a/phpBB/includes/functions_install.php
+++ b/phpBB/includes/functions_install.php
@@ -21,6 +21,12 @@ if (!defined('IN_PHPBB'))
*/
function can_load_dll($dll)
{
+ // SQLite2 is a tricky thing, from 5.0.0 it requires PDO; if PDO is not loaded we must state that SQLite is unavailable
+ // as the installer doesn't understand that the extension has a prerequisite.
+ if ($dll == 'sqlite' && version_compare(PHP_VERSION, '5.0.0', '>=') && !extension_loaded('pdo'))
+ {
+ return false;
+ }
return ((@ini_get('enable_dl') || strtolower(@ini_get('enable_dl')) == 'on') && (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') && function_exists('dl') && @dl($dll . '.' . PHP_SHLIB_SUFFIX)) ? true : false;
}
@@ -175,7 +181,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
function dbms_select($default = '', $only_20x_options = false)
{
global $lang;
-
+
$available_dbms = get_available_dbms(false, false, $only_20x_options);
$dbms_options = '';
foreach ($available_dbms as $dbms_name => $details)
@@ -396,10 +402,10 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
}
else
{
- $sql = "SELECT FIRST 0 char_length('')
- FROM RDB\$DATABASE";
+ $sql = 'SELECT 1 FROM RDB$DATABASE
+ WHERE BIN_AND(10, 1) = 0';
$result = $db->sql_query($sql);
- if (!$result) // This can only fail if char_length is not defined
+ if (!$result) // This can only fail if BIN_AND is not defined
{
$error[] = $lang['INST_ERR_DB_NO_FIREBIRD'];
}
@@ -440,7 +446,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
unset($final);
}
break;
-
+
case 'oracle':
if ($unicode_check)
{
@@ -462,7 +468,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
}
}
break;
-
+
case 'postgres':
if ($unicode_check)
{
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 4fd5fd19e0..0fcf33f999 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -27,6 +27,8 @@ class messenger
var $mail_priority = MAIL_NORMAL_PRIORITY;
var $use_queue = true;
+
+ var $tpl_obj = NULL;
var $tpl_msg = array();
var $eol = "\n";
@@ -171,13 +173,13 @@ class messenger
/**
* Set email template to use
*/
- function template($template_file, $template_lang = '')
+ function template($template_file, $template_lang = '', $template_path = '')
{
global $config, $phpbb_root_path, $user;
if (!trim($template_file))
{
- trigger_error('No template file set', E_USER_ERROR);
+ trigger_error('No template file for emailing set.', E_USER_ERROR);
}
if (!trim($template_lang))
@@ -185,25 +187,28 @@ class messenger
$template_lang = basename($config['default_lang']);
}
- if (empty($this->tpl_msg[$template_lang . $template_file]))
+ // tpl_msg now holds a template object we can use to parse the template file
+ if (!isset($this->tpl_msg[$template_lang . $template_file]))
{
- $tpl_file = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
- $tpl_file .= $template_lang . "/email/$template_file.txt";
+ $this->tpl_msg[$template_lang . $template_file] = new template();
+ $tpl = &$this->tpl_msg[$template_lang . $template_file];
- if (!file_exists($tpl_file))
+ if (!$template_path)
{
- trigger_error("Could not find email template file [ $tpl_file ]", E_USER_ERROR);
+ $template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
+ $template_path .= $template_lang . '/email';
}
- if (($data = @file_get_contents($tpl_file)) === false)
- {
- trigger_error("Failed opening template file [ $tpl_file ]", E_USER_ERROR);
- }
+ $tpl->set_custom_template($template_path, $template_lang . '_email');
- $this->tpl_msg[$template_lang . $template_file] = $data;
+ $tpl->set_filenames(array(
+ 'body' => $template_file . '.txt',
+ ));
}
- $this->msg = $this->tpl_msg[$template_lang . $template_file];
+ $this->tpl_obj = &$this->tpl_msg[$template_lang . $template_file];
+ $this->vars = &$this->tpl_obj->_rootref;
+ $this->tpl_msg = '';
return true;
}
@@ -213,7 +218,22 @@ class messenger
*/
function assign_vars($vars)
{
- $this->vars = (empty($this->vars)) ? $vars : $this->vars + $vars;
+ if (!is_object($this->tpl_obj))
+ {
+ return;
+ }
+
+ $this->tpl_obj->assign_vars($vars);
+ }
+
+ function assign_block_vars($blockname, $vars)
+ {
+ if (!is_object($this->tpl_obj))
+ {
+ return;
+ }
+
+ $this->tpl_obj->assign_block_vars($blockname, $vars);
}
/**
@@ -224,15 +244,32 @@ class messenger
global $config, $user;
// We add some standard variables we always use, no need to specify them always
- $this->vars['U_BOARD'] = (!isset($this->vars['U_BOARD'])) ? generate_board_url() : $this->vars['U_BOARD'];
- $this->vars['EMAIL_SIG'] = (!isset($this->vars['EMAIL_SIG'])) ? str_replace('
', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])) : $this->vars['EMAIL_SIG'];
- $this->vars['SITENAME'] = (!isset($this->vars['SITENAME'])) ? htmlspecialchars_decode($config['sitename']) : $this->vars['SITENAME'];
+ if (!isset($this->vars['U_BOARD']))
+ {
+ $this->assign_vars(array(
+ 'U_BOARD' => generate_board_url(),
+ ));
+ }
- // Escape all quotes, else the eval will fail.
- $this->msg = str_replace ("'", "\'", $this->msg);
- $this->msg = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . ((isset(\$this->vars['\\1'])) ? \$this->vars['\\1'] : '') . '", $this->msg);
+ if (!isset($this->vars['EMAIL_SIG']))
+ {
+ $this->assign_vars(array(
+ 'EMAIL_SIG' => str_replace('
', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])),
+ ));
+ }
- eval("\$this->msg = '$this->msg';");
+ if (!isset($this->vars['SITENAME']))
+ {
+ $this->assign_vars(array(
+ 'SITENAME' => htmlspecialchars_decode($config['sitename']),
+ ));
+ }
+
+ // Parse message through template
+ $this->msg = trim($this->tpl_obj->assign_display('body'));
+
+ // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding
+ $this->msg = str_replace("\r\n", "\n", $this->msg);
// We now try and pull a subject from the email body ... if it exists,
// do this here because the subject may contain a variable
@@ -356,7 +393,7 @@ class messenger
$headers[] = 'X-Priority: ' . $this->mail_priority;
$headers[] = 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High'));
- $headers[] = 'X-Mailer: PhpBB3';
+ $headers[] = 'X-Mailer: phpBB3';
$headers[] = 'X-MimeOLE: phpBB3';
$headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url());
@@ -408,6 +445,8 @@ class messenger
$this->from = '<' . $config['board_contact'] . '>';
}
+ $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol;
+
// Build to, cc and bcc strings
$to = $cc = $bcc = '';
foreach ($this->addresses as $type => $address_ary)
@@ -419,7 +458,7 @@ class messenger
foreach ($address_ary as $which_ary)
{
- $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? '"' . mail_encode($which_ary['name']) . '" <' . $which_ary['email'] . '>' : $which_ary['email']);
+ $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']);
}
}
@@ -438,13 +477,7 @@ class messenger
}
else
{
- // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used...
- // Reference: http://bugs.php.net/bug.php?id=15841
- $headers = implode($this->eol, $headers);
-
- ob_start();
- $result = $config['email_function_name']($mail_to, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $headers);
- $err_msg = ob_get_clean();
+ $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg);
}
if (!$result)
@@ -687,9 +720,7 @@ class queue
}
else
{
- ob_start();
- $result = $config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), implode($this->eol, $headers));
- $err_msg = ob_get_clean();
+ $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg);
}
if (!$result)
@@ -1441,13 +1472,15 @@ class smtp_class
* is basically doomed with an unreadable subject.
*
* Please note that this version fully supports RFC 2045 section 6.8.
+*
+* @param string $eol End of line we are using (optional to be backwards compatible)
*/
-function mail_encode($str)
+function mail_encode($str, $eol = "\r\n")
{
// define start delimimter, end delimiter and spacer
$start = "=?UTF-8?B?";
$end = "?=";
- $delimiter = "\r\n ";
+ $delimiter = "$eol ";
// Maximum length is 75. $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $delimiter . $end)!!!
$split_length = 60;
@@ -1484,4 +1517,25 @@ function mail_encode($str)
return substr($str, 0, -strlen($delimiter));
}
+/**
+* Wrapper for sending out emails with the PHP's mail function
+*/
+function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)
+{
+ global $config;
+
+ // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used...
+ // Reference: http://bugs.php.net/bug.php?id=15841
+ $headers = implode($eol, $headers);
+
+ ob_start();
+ // On some PHP Versions mail() *may* fail if there are newlines within the subject.
+ // Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8.
+ // Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used)
+ $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers);
+ $err_msg = ob_get_clean();
+
+ return $result;
+}
+
?>
\ No newline at end of file
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 07c8944992..069740ebda 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -24,6 +24,8 @@ function generate_smilies($mode, $forum_id)
global $auth, $db, $user, $config, $template;
global $phpEx, $phpbb_root_path;
+ $start = request_var('start', 0);
+
if ($mode == 'window')
{
if ($forum_id)
@@ -44,9 +46,26 @@ function generate_smilies($mode, $forum_id)
page_header($user->lang['SMILIES']);
+ $sql = 'SELECT COUNT(smiley_id) AS count
+ FROM ' . SMILIES_TABLE . '
+ GROUP BY smiley_url';
+ $result = $db->sql_query($sql, 3600);
+
+ $smiley_count = 0;
+ while ($row = $db->sql_fetchrow($result))
+ {
+ ++$smiley_count;
+ }
+ $db->sql_freeresult($result);
+
$template->set_filenames(array(
'body' => 'posting_smilies.html')
);
+
+ $template->assign_var('PAGINATION',
+ generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id),
+ $smiley_count, $config['smilies_per_page'], $start, true)
+ );
}
$display_link = false;
@@ -64,13 +83,22 @@ function generate_smilies($mode, $forum_id)
$db->sql_freeresult($result);
}
- $last_url = '';
-
- $sql = 'SELECT *
- FROM ' . SMILIES_TABLE .
- (($mode == 'inline') ? ' WHERE display_on_posting = 1 ' : '') . '
- ORDER BY smiley_order';
- $result = $db->sql_query($sql, 3600);
+ if ($mode == 'window')
+ {
+ $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height
+ FROM ' . SMILIES_TABLE . '
+ GROUP BY smiley_url, smiley_width, smiley_height
+ ORDER BY smiley_order';
+ $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600);
+ }
+ else
+ {
+ $sql = 'SELECT *
+ FROM ' . SMILIES_TABLE . '
+ WHERE display_on_posting = 1
+ ORDER BY smiley_order';
+ $result = $db->sql_query($sql, 3600);
+ }
$smilies = array();
while ($row = $db->sql_fetchrow($result))
@@ -84,12 +112,14 @@ function generate_smilies($mode, $forum_id)
if (sizeof($smilies))
{
+ $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
+
foreach ($smilies as $row)
{
$template->assign_block_vars('smiley', array(
'SMILEY_CODE' => $row['code'],
'A_SMILEY_CODE' => addslashes($row['code']),
- 'SMILEY_IMG' => $phpbb_root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
+ 'SMILEY_IMG' => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'],
'SMILEY_WIDTH' => $row['smiley_width'],
'SMILEY_HEIGHT' => $row['smiley_height'],
'SMILEY_DESC' => $row['emotion'])
@@ -656,6 +686,7 @@ function create_thumbnail($source, $destination, $mimetype)
break;
case IMG_JPG:
+ @ini_set('gd.jpeg_ignore_warning', 1);
$image = @imagecreatefromjpeg($source);
break;
@@ -668,6 +699,11 @@ function create_thumbnail($source, $destination, $mimetype)
break;
}
+ if (empty($image))
+ {
+ return false;
+ }
+
if ($type['version'] == 1)
{
$new_image = imagecreate($new_width, $new_height);
@@ -751,7 +787,7 @@ function posting_gen_inline_attachments(&$attachment_data)
foreach ($attachment_data as $i => $attachment)
{
- $s_inline_attachment_options .= '
';
+ $s_inline_attachment_options .= '
';
}
$template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
@@ -785,7 +821,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a
foreach ($attachment_data as $count => $attach_row)
{
$hidden = '';
- $attach_row['real_filename'] = basename($attach_row['real_filename']);
+ $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']);
foreach ($attach_row as $key => $value)
{
@@ -795,8 +831,8 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a
$download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false);
$template->assign_block_vars('attach_row', array(
- 'FILENAME' => basename($attach_row['real_filename']),
- 'A_FILENAME' => addslashes(basename($attach_row['real_filename'])),
+ 'FILENAME' => utf8_basename($attach_row['real_filename']),
+ 'A_FILENAME' => addslashes(utf8_basename($attach_row['real_filename'])),
'FILE_COMMENT' => $attach_row['attach_comment'],
'ATTACH_ID' => $attach_row['attach_id'],
'S_IS_ORPHAN' => $attach_row['is_orphan'],
@@ -818,7 +854,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a
/**
* Load Drafts
*/
-function load_drafts($topic_id = 0, $forum_id = 0, $id = 0)
+function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0)
{
global $user, $db, $template, $auth;
global $phpbb_root_path, $phpEx;
@@ -911,7 +947,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0)
{
// Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards...
$link_pm = true;
- $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}");
+ $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}" . (($pm_action) ? "&action=$pm_action" : '') . (($msg_id) ? "&p=$msg_id" : ''));
}
$template->assign_block_vars('draftrow', array(
@@ -944,6 +980,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
WHERE p.topic_id = $topic_id
" . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . '
' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '
+ ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '
ORDER BY p.post_time ';
$sql .= ($mode == 'post_review') ? 'ASC' : 'DESC';
$result = $db->sql_query_limit($sql, $config['posts_per_page']);
@@ -962,6 +999,12 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
return false;
}
+ // Handle 'post_review_edit' like 'post_review' from now on
+ if ($mode == 'post_review_edit')
+ {
+ $mode = 'post_review';
+ }
+
$sql = $db->sql_build_query('SELECT', array(
'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe',
@@ -1514,6 +1557,21 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)
break;
}
+ if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))
+ {
+ $sql = 'SELECT 1 AS has_attachments
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query_limit($sql, 1);
+ $has_attachments = (int) $db->sql_fetchfield('has_attachments');
+ $db->sql_freeresult($result);
+
+ if (!$has_attachments)
+ {
+ $sql_data[TOPICS_TABLE] .= ', topic_attachment = 0';
+ }
+ }
+
// $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : '';
$db->sql_transaction('begin');
@@ -1565,8 +1623,9 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)
/**
* Submit Post
+* @todo Split up and create lightweight, simple API for this.
*/
-function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true)
+function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
{
global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path;
@@ -1618,14 +1677,22 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval
+ // The variable name should be $post_approved, because it indicates if the post is approved or not
$post_approval = 1;
- // Check the permissions for post approval, as well as the queue trigger where users are put on approval with a post count lower than specified. Moderators are not affected.
- if ((($config['enable_queue_trigger'] && $user->data['user_posts'] < $config['queue_trigger_posts']) || !$auth->acl_get('f_noapprove', $data['forum_id'])) && !$auth->acl_get('m_approve', $data['forum_id']))
+ // Check the permissions for post approval. Moderators are not affected.
+ if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']))
{
+ // Post not approved, but in queue
$post_approval = 0;
}
+ // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved
+ if (isset($data['force_approved_state']))
+ {
+ $post_approval = ($data['force_approved_state']) ? 1 : 0;
+ }
+
// Start the transaction here
$db->sql_transaction('begin');
@@ -2119,7 +2186,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
else
{
// insert attachment into db
- if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
+ if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
{
continue;
}
@@ -2423,7 +2490,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Index message contents
- if ($update_message && $data['enable_indexing'])
+ if ($update_search_index && $data['enable_indexing'])
{
// Select the search method and do some additional checks to ensure it can actually be utilised
$search_type = basename($config['search_type']);
@@ -2475,7 +2542,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Mark this topic as read
// We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
- markread('topic', $data['forum_id'], $data['topic_id'], time());
+ markread('topic', (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']), $data['topic_id'], time());
//
if ($config['load_db_lastread'] && $user->data['is_registered'])
@@ -2483,7 +2550,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$sql = 'SELECT mark_time
FROM ' . FORUMS_TRACK_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
- AND forum_id = ' . $data['forum_id'];
+ AND forum_id = ' . (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']);
$result = $db->sql_query($sql);
$f_mark_time = (int) $db->sql_fetchfield('mark_time');
$db->sql_freeresult($result);
@@ -2496,14 +2563,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
{
// Update forum info
- $sql = 'SELECT forum_last_post_time
- FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . $data['forum_id'];
+ if ($topic_type == POST_GLOBAL)
+ {
+ $sql = 'SELECT MAX(topic_last_post_time) as forum_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE forum_id = 0';
+ }
+ else
+ {
+ $sql = 'SELECT forum_last_post_time
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $data['forum_id'];
+ }
$result = $db->sql_query($sql);
$forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
$db->sql_freeresult($result);
- update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
+ update_forum_tracking_info((($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']), $forum_last_post_time, $f_mark_time, false);
}
// Send Notifications
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index 05653f7e3b..848218ca83 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -1145,8 +1145,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false)
{
$sql = 'SELECT user_id, username, user_colour
FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $u) . '
- AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
+ WHERE ' . $db->sql_in_set('user_id', $u);
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -1356,6 +1355,12 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
while ($row = $db->sql_fetchrow($result))
{
+ // Additionally, do not include the sender if he is in the group he wants to send to. ;)
+ if ($row['user_id'] === $user->data['user_id'])
+ {
+ continue;
+ }
+
$field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
$recipients[$row['user_id']] = $field;
}
@@ -1405,7 +1410,8 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
'bbcode_bitfield' => $data['bbcode_bitfield'],
'bbcode_uid' => $data['bbcode_uid'],
'to_address' => implode(':', $to),
- 'bcc_address' => implode(':', $bcc)
+ 'bcc_address' => implode(':', $bcc),
+ 'message_reported' => 0,
);
break;
@@ -1545,7 +1551,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
else
{
// insert attachment into db
- if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
+ if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
{
continue;
}
@@ -1691,14 +1697,34 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode
{
global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode;
+ // Select all receipts and the author from the pm we currently view, to only display their pm-history
+ $sql = 'SELECT author_id, user_id
+ FROM ' . PRIVMSGS_TO_TABLE . "
+ WHERE msg_id = $msg_id
+ AND folder_id <> " . PRIVMSGS_HOLD_BOX;
+ $result = $db->sql_query($sql);
+
+ $recipients = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $recipients[] = (int) $row['user_id'];
+ $recipients[] = (int) $row['author_id'];
+ }
+ $db->sql_freeresult($result);
+ $recipients = array_unique($recipients);
+
// Get History Messages (could be newer)
$sql = 'SELECT t.*, p.*, u.*
FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u
WHERE t.msg_id = p.msg_id
AND p.author_id = u.user_id
- AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ")
+ AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
+ AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . "
AND t.user_id = $user_id";
+ // We no longer need those.
+ unset($recipients);
+
if (!$message_row['root_level'])
{
$sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
@@ -1781,7 +1807,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode
$decoded_message = false;
- if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id'])
+ if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS)
{
$decoded_message = $message;
decode_message($decoded_message, $row['bbcode_uid']);
@@ -1824,10 +1850,10 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode
'MSG_ID' => $row['msg_id'],
'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'],
- 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id']) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '',
+ 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '',
'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '')
);
- unset($rowset[$id]);
+ unset($rowset[$i]);
$prev_id = $id;
}
@@ -1863,4 +1889,93 @@ function set_user_message_limit()
$user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
}
+/**
+* Generates an array of coloured recipient names from a list of PMs - (groups & users)
+*
+* @param array $pm_by_id An array of rows from PRIVMSGS_TABLE, keys are the msg_ids.
+*
+* @return array 2D Array: array(msg_id => array('username or group string', ...), ...)
+* Usernames are generated with {@link get_username_string get_username_string}
+* Groups are coloured and have a link to the membership page
+*/
+function get_recipient_strings($pm_by_id)
+{
+ global $user, $db;
+
+ $address_list = $recipient_list = $address = array();
+
+ $_types = array('u', 'g');
+
+ foreach ($pm_by_id as $message_id => $row)
+ {
+ $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address']));
+
+ foreach ($_types as $ug_type)
+ {
+ if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type]))
+ {
+ foreach ($address[$message_id][$ug_type] as $ug_id => $in_to)
+ {
+ $recipient_list[$ug_type][$ug_id] = array('name' => $user->lang['NA'], 'colour' => '');
+ }
+ }
+ }
+ }
+
+ foreach ($_types as $ug_type)
+ {
+ if (!empty($recipient_list[$ug_type]))
+ {
+ if ($ug_type == 'u')
+ {
+ $sql = 'SELECT user_id as id, username as name, user_colour as colour
+ FROM ' . USERS_TABLE . '
+ WHERE ';
+ }
+ else
+ {
+ $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type
+ FROM ' . GROUPS_TABLE . '
+ WHERE ';
+ }
+ $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type])));
+
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ if ($ug_type == 'g')
+ {
+ $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name'];
+ }
+
+ $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
+ }
+ $db->sql_freeresult($result);
+ }
+ }
+
+ foreach ($address as $message_id => $adr_ary)
+ {
+ foreach ($adr_ary as $type => $id_ary)
+ {
+ foreach ($id_ary as $ug_id => $_id)
+ {
+ if ($type == 'u')
+ {
+ $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']);
+ }
+ else
+ {
+ $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : '';
+ $link = '
';
+ $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '' : '');
+ }
+ }
+ }
+ }
+
+ return $address_list;
+}
+
?>
\ No newline at end of file
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 26a1feb126..9e356414a9 100644
--- a/phpBB/includes/functions_profile_fields.php
+++ b/phpBB/includes/functions_profile_fields.php
@@ -90,18 +90,6 @@ class custom_profile
*/
function validate_profile_field($field_type, &$field_value, $field_data)
{
- switch ($field_type)
- {
- case FIELD_INT:
- case FIELD_DROPDOWN:
- $field_value = (int) $field_value;
- break;
-
- case FIELD_BOOL:
- $field_value = (bool) $field_value;
- break;
- }
-
switch ($field_type)
{
case FIELD_DATE:
@@ -133,6 +121,8 @@ class custom_profile
break;
case FIELD_BOOL:
+ $field_value = (bool) $field_value;
+
if (!$field_value && $field_data['field_required'])
{
return 'FIELD_REQUIRED';
@@ -140,10 +130,12 @@ class custom_profile
break;
case FIELD_INT:
- if (empty($field_value) && !$field_data['field_required'])
+ if (trim($field_value) === '' && !$field_data['field_required'])
{
return false;
}
+
+ $field_value = (int) $field_value;
if ($field_value < $field_data['field_minlen'])
{
@@ -156,6 +148,8 @@ class custom_profile
break;
case FIELD_DROPDOWN:
+ $field_value = (int) $field_value;
+
if ($field_value == $field_data['field_novalue'] && $field_data['field_required'])
{
return 'FIELD_REQUIRED';
@@ -259,7 +253,7 @@ class custom_profile
}
/**
- * Submit profile field
+ * Submit profile field for validation
* @access public
*/
function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error)
@@ -349,6 +343,66 @@ class custom_profile
$db->sql_freeresult($result);
}
+ /**
+ * Update profile field data directly
+ */
+ function update_profile_field_data($user_id, &$cp_data)
+ {
+ global $db;
+
+ if (!sizeof($cp_data))
+ {
+ return;
+ }
+
+ switch ($db->sql_layer)
+ {
+ case 'oracle':
+ case 'firebird':
+ case 'postgres':
+ $right_delim = $left_delim = '"';
+ break;
+
+ case 'sqlite':
+ case 'mssql':
+ case 'mssql_odbc':
+ $right_delim = ']';
+ $left_delim = '[';
+ break;
+
+ case 'mysql':
+ case 'mysql4':
+ case 'mysqli':
+ $right_delim = $left_delim = '`';
+ break;
+ }
+
+ // use new array for the UPDATE; changes in the key do not affect the original array
+ $cp_data_sql = array();
+ foreach ($cp_data as $key => $value)
+ {
+ // Firebird is case sensitive with delimiter
+ $cp_data_sql[$left_delim . (($db->sql_layer == 'firebird' || $db->sql_layer == 'oracle') ? strtoupper($key) : $key) . $right_delim] = $value;
+ }
+
+ $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $cp_data_sql) . "
+ WHERE user_id = $user_id";
+ $db->sql_query($sql);
+
+ if (!$db->sql_affectedrows())
+ {
+ $cp_data_sql['user_id'] = (int) $user_id;
+
+ $db->sql_return_on_error(true);
+
+ $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data_sql);
+ $db->sql_query($sql);
+
+ $db->sql_return_on_error(false);
+ }
+ }
+
/**
* Assign fields to template, used for viewprofile, viewtopic and memberlist (if load setting is enabled)
* This is directly connected to the user -> mode == grab is to grab the user specific fields, mode == show is for assigning the row to the template
@@ -454,7 +508,7 @@ class custom_profile
switch ($this->profile_types[$field_type])
{
case 'int':
- if ($value == '')
+ if ($value === '')
{
return NULL;
}
@@ -584,7 +638,7 @@ class custom_profile
}
}
- return (is_null($value)) ? '' : (int) $value;
+ return (is_null($value) || $value === '') ? '' : (int) $value;
}
else
{
diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php
index 42a5eb3248..1d3a4d74f8 100644
--- a/phpBB/includes/functions_template.php
+++ b/phpBB/includes/functions_template.php
@@ -128,9 +128,9 @@ class template_compile
$php_blocks = $matches[1];
$code = preg_replace('#.*?#s', '', $code);
- preg_match_all('##', $code, $matches);
+ preg_match_all('##', $code, $matches);
$include_blocks = $matches[1];
- $code = preg_replace('##', '', $code);
+ $code = preg_replace('##', '', $code);
preg_match_all('##', $code, $matches);
$includephp_blocks = $matches[1];
@@ -193,8 +193,39 @@ class template_compile
case 'INCLUDE':
$temp = array_shift($include_blocks);
+
+ // Dynamic includes
+ // Cheap match rather than a full blown regexp, we already know
+ // the format of the input so just use string manipulation.
+ if ($temp[0] == '{')
+ {
+ $file = false;
+
+ if ($temp[1] == '$')
+ {
+ $var = substr($temp, 2, -1);
+ //$file = $this->template->_tpldata['DEFINE']['.'][$var];
+ $temp = "\$this->_tpldata['DEFINE']['.']['$var']";
+ }
+ else
+ {
+ $var = substr($temp, 1, -1);
+ //$file = $this->template->_rootref[$var];
+ $temp = "\$this->_rootref['$var']";
+ }
+ }
+ else
+ {
+ $file = $temp;
+ }
+
$compile_blocks[] = 'compile_tag_include($temp) . ' ?>';
- $this->template->_tpl_include($temp, false);
+
+ // No point in checking variable includes
+ if ($file)
+ {
+ $this->template->_tpl_include($file, false);
+ }
break;
case 'INCLUDEPHP':
@@ -220,15 +251,22 @@ class template_compile
$template_php .= (!$no_echo) ? (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '') : (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '');
}
+ // Remove unused opening/closing tags
+ $template_php = str_replace(' ?>([\r\n])#', '?>\1\1', $template_php);
+
// There will be a number of occasions where we switch into and out of
// PHP mode instantaneously. Rather than "burden" the parser with this
// we'll strip out such occurences, minimising such switching
if ($no_echo)
{
- return "\$$echo_var .= '" . str_replace(' ?>_tpl_include($tag_args); }";
+ }
+
return "\$this->_tpl_include('$tag_args');";
}
@@ -603,7 +647,7 @@ class template_compile
*/
function compile_tag_include_php($tag_args)
{
- return "include('" . $tag_args . "');";
+ return "\$this->_php_include('$tag_args');";
}
/**
diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php
index c345f81e1d..046abede8e 100644
--- a/phpBB/includes/functions_transfer.php
+++ b/phpBB/includes/functions_transfer.php
@@ -316,15 +316,15 @@ class ftp extends transfer
return 'ERR_CONNECTING_SERVER';
}
- // attempt to turn pasv mode on
- @ftp_pasv($this->connection, true);
-
// login to the server
if (!@ftp_login($this->connection, $this->username, $this->password))
{
return 'ERR_UNABLE_TO_LOGIN';
}
+ // attempt to turn pasv mode on
+ @ftp_pasv($this->connection, true);
+
// change to the root directory
if (!$this->_chdir($this->root_path))
{
@@ -462,6 +462,20 @@ class ftp extends transfer
{
$list = @ftp_nlist($this->connection, $dir);
+ // See bug #46295 - Some FTP daemons don't like './'
+ if ($dir === './')
+ {
+ // Let's try some alternatives
+ $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list;
+ $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list;
+ }
+
+ // Return on error
+ if ($list === false)
+ {
+ return false;
+ }
+
// Remove path if prepended
foreach ($list as $key => $item)
{
@@ -469,7 +483,7 @@ class ftp extends transfer
$item = str_replace('\\', '/', $item);
$dir = str_replace('\\', '/', $dir);
- if (strpos($item, $dir) === 0)
+ if (!empty($dir) && strpos($item, $dir) === 0)
{
$item = substr($item, strlen($dir));
}
@@ -723,13 +737,32 @@ class ftp_fsock extends transfer
$list = array();
while (!@feof($this->data_connection))
{
- $list[] = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512));
+ $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512));
+
+ if ($filename !== '')
+ {
+ $list[] = $filename;
+ }
}
$this->_close_data_connection();
// Clear buffer
$this->_check_command();
+ // See bug #46295 - Some FTP daemons don't like './'
+ if ($dir === './' && empty($list))
+ {
+ // Let's try some alternatives
+ $list = $this->_ls('.');
+
+ if (empty($list))
+ {
+ $list = $this->_ls('');
+ }
+
+ return $list;
+ }
+
// Remove path if prepended
foreach ($list as $key => $item)
{
@@ -737,7 +770,7 @@ class ftp_fsock extends transfer
$item = str_replace('\\', '/', $item);
$dir = str_replace('\\', '/', $dir);
- if (strpos($item, $dir) === 0)
+ if (!empty($dir) && strpos($item, $dir) === 0)
{
$item = substr($item, strlen($dir));
}
@@ -826,7 +859,7 @@ class ftp_fsock extends transfer
$result = @fgets($this->connection, 512);
$response .= $result;
}
- while (substr($response, 3, 1) != ' ');
+ while (substr($result, 3, 1) !== ' ');
if (!preg_match('#^[123]#', $response))
{
diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php
index 1ad6223aa1..a7abb06674 100644
--- a/phpBB/includes/functions_upload.php
+++ b/phpBB/includes/functions_upload.php
@@ -58,7 +58,7 @@ class filespec
$this->filename = $upload_ary['tmp_name'];
$this->filesize = $upload_ary['size'];
- $name = trim(htmlspecialchars(basename($upload_ary['name'])));
+ $name = trim(utf8_htmlspecialchars(utf8_basename($upload_ary['name'])));
$this->realname = $this->uploadname = (STRIP) ? stripslashes($name) : $name;
$this->mimetype = $upload_ary['type'];
@@ -290,7 +290,7 @@ class filespec
$upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy';
$upload_mode = ($this->local) ? 'local' : $upload_mode;
- $this->destination_file = $this->destination_path . '/' . basename($this->realname);
+ $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
// Check if the file already exist, else there is something wrong...
if (file_exists($this->destination_file) && !$overwrite)
@@ -313,12 +313,9 @@ class filespec
if (!@move_uploaded_file($this->filename, $this->destination_file))
{
$this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- return false;
}
}
- @unlink($this->filename);
-
break;
case 'move':
@@ -328,12 +325,9 @@ class filespec
if (!@copy($this->filename, $this->destination_file))
{
$this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- return false;
}
}
- @unlink($this->filename);
-
break;
case 'local':
@@ -341,14 +335,21 @@ class filespec
if (!@copy($this->filename, $this->destination_file))
{
$this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
- return false;
}
- @unlink($this->filename);
break;
}
+ // Remove temporary filename
+ @unlink($this->filename);
+
+ if (sizeof($this->error))
+ {
+ return false;
+ }
+
phpbb_chmod($this->destination_file, $chmod);
+ return true;
}
// Try to get real filesize from destination folder
@@ -417,10 +418,9 @@ class filespec
// Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
{
- $size_lang = ($this->upload->max_filesize >= 1048576) ? $user->lang['MIB'] : (($this->upload->max_filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES'] );
$max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
- $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang);
+ $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
return false;
}
@@ -635,7 +635,7 @@ class fileupload
if ($filedata === false)
{
- $_FILES[$form_name]['name'] = basename($source_file);
+ $_FILES[$form_name]['name'] = utf8_basename($source_file);
$_FILES[$form_name]['size'] = 0;
$mimetype = '';
@@ -747,7 +747,7 @@ class fileupload
$ext = array_pop($url['path']);
$url['path'] = implode('', $url['path']);
- $upload_ary['name'] = basename($url['path']) . (($ext) ? '.' . $ext : '');
+ $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
$filename = $url['path'];
$filesize = 0;
@@ -855,10 +855,9 @@ class fileupload
break;
case 2:
- $size_lang = ($this->max_filesize >= 1048576) ? $user->lang['MIB'] : (($this->max_filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES']);
$max_filesize = get_formatted_filesize($this->max_filesize, false);
- $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang);
+ $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
break;
case 3:
@@ -891,10 +890,9 @@ class fileupload
// Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0))
{
- $size_lang = ($this->max_filesize >= 1048576) ? $user->lang['MIB'] : (($this->max_filesize >= 1024) ? $user->lang['KIB'] : $user->lang['BYTES']);
$max_filesize = get_formatted_filesize($this->max_filesize, false);
- $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang);
+ $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
}
// check Filename
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 027db39751..7255d138ab 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -171,7 +171,7 @@ function user_add($user_row, $cp_data = false)
'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '',
'user_pass_convert' => 0,
'user_email' => strtolower($user_row['user_email']),
- 'user_email_hash' => crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email']),
+ 'user_email_hash' => phpbb_email_hash($user_row['user_email']),
'group_id' => $user_row['group_id'],
'user_type' => $user_row['user_type'],
);
@@ -187,7 +187,9 @@ function user_add($user_row, $cp_data = false)
'user_ip' => '',
'user_regdate' => time(),
'user_passchg' => time(),
- 'user_options' => 895,
+ 'user_options' => 230271,
+ // We do not set the new flag here - registration scripts need to specify it
+ 'user_new' => 0,
'user_inactive_reason' => 0,
'user_inactive_time' => 0,
@@ -275,8 +277,38 @@ function user_add($user_row, $cp_data = false)
// Now make it the users default group...
group_set_user_default($user_row['group_id'], array($user_id), false);
+ // Add to newly registered users group if user_new is 1
+ if ($config['new_member_post_limit'] && $sql_ary['user_new'])
+ {
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = 'NEWLY_REGISTERED'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $db->sql_query($sql);
+ $add_group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+
+ if ($add_group_id)
+ {
+ // Because these actions only fill the log unneccessarily we skip the add_log() entry with a little hack. :/
+ $GLOBALS['skip_add_log'] = true;
+
+ // Add user to "newly registered users" group and set to default group if admin specified so.
+ if ($config['new_member_group_default'])
+ {
+ group_user_add($add_group_id, $user_id, false, false, true);
+ }
+ else
+ {
+ group_user_add($add_group_id, $user_id);
+ }
+
+ unset($GLOBALS['skip_add_log']);
+ }
+ }
+
// set the newest user and adjust the user count if the user is a normal user and no activation mail is sent
- if ($user_row['user_type'] == USER_NORMAL)
+ if ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_FOUNDER)
{
set_config('newest_user_id', $user_id, true);
set_config('newest_username', $user_row['username'], true);
@@ -421,6 +453,11 @@ function user_delete($mode, $user_id, $post_username = false)
WHERE topic_last_poster_id = $user_id";
$db->sql_query($sql);
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET poster_id = ' . ANONYMOUS . "
+ WHERE poster_id = $user_id";
+ $db->sql_query($sql);
+
// Since we change every post by this author, we need to count this amount towards the anonymous user
// Update the post count for the anonymous user
@@ -501,6 +538,23 @@ function user_delete($mode, $user_id, $post_username = false)
$cache->destroy('sql', MODERATOR_CACHE_TABLE);
+ // Delete user log entries about this user
+ $sql = 'DELETE FROM ' . LOG_TABLE . '
+ WHERE reportee_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ // Change user_id to anonymous for this users triggered events
+ $sql = 'UPDATE ' . LOG_TABLE . '
+ SET user_id = ' . ANONYMOUS . '
+ WHERE user_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ // Delete the user_id from the zebra table
+ $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
+ WHERE user_id = ' . $user_id . '
+ OR zebra_id = ' . $user_id;
+ $db->sql_query($sql);
+
// Delete the user_id from the banlist
$sql = 'DELETE FROM ' . BANLIST_TABLE . '
WHERE ban_userid = ' . $user_id;
@@ -904,7 +958,8 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
}
}
}
- else
+
+ if (empty($banlist_ary))
{
trigger_error('NO_IPS_DEFINED');
}
@@ -977,7 +1032,17 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
}
while ($row = $db->sql_fetchrow($result));
- $banlist_ary = array_unique(array_diff($banlist_ary, $banlist_ary_tmp));
+ $banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp);
+
+ if (sizeof($banlist_ary_tmp))
+ {
+ // One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length
+ $sql = 'DELETE FROM ' . BANLIST_TABLE . '
+ WHERE ' . $db->sql_in_set($type, $banlist_ary_tmp) . '
+ AND ban_exclude = ' . (int) $ban_exclude;
+ $db->sql_query($sql);
+ }
+
unset($banlist_ary_tmp);
}
$db->sql_freeresult($result);
@@ -1060,9 +1125,16 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
// Update log
$log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_';
- // Add to moderator and admin log
+ // Add to moderator log, admin log and user notes
add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
+ if ($mode == 'user')
+ {
+ foreach ($banlist_ary as $user_id)
+ {
+ add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
+ }
+ }
$cache->destroy('sql', BANLIST_TABLE);
@@ -1101,7 +1173,7 @@ function user_unban($mode, $ban)
switch ($mode)
{
case 'user':
- $sql = 'SELECT u.username AS unban_info
+ $sql = 'SELECT u.username AS unban_info, u.user_id
FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b
WHERE ' . $db->sql_in_set('b.ban_id', $unban_sql) . '
AND u.user_id = b.ban_userid';
@@ -1122,9 +1194,14 @@ function user_unban($mode, $ban)
$result = $db->sql_query($sql);
$l_unban_list = '';
+ $user_ids_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info'];
+ if ($mode == 'user')
+ {
+ $user_ids_ary[] = $row['user_id'];
+ }
}
$db->sql_freeresult($result);
@@ -1132,9 +1209,16 @@ function user_unban($mode, $ban)
WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
$db->sql_query($sql);
- // Add to moderator and admin log
+ // Add to moderator log, admin log and user notes
add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
+ if ($mode == 'user')
+ {
+ foreach ($user_ids_ary as $user_id)
+ {
+ add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
+ }
+ }
}
$cache->destroy('sql', BANLIST_TABLE);
@@ -1643,7 +1727,7 @@ function validate_email($email, $allowed_email = false)
{
$sql = 'SELECT user_email_hash
FROM ' . USERS_TABLE . "
- WHERE user_email_hash = " . (crc32($email) . strlen($email));
+ WHERE user_email_hash = " . $db->sql_escape(phpbb_email_hash($email));
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -2077,8 +2161,8 @@ function avatar_gallery($category, $avatar_select, $items_per_column, $block_var
if (preg_match('#^[^&\'"<>]+\.(?:gif|png|jpe?g)$#i', $sub_file))
{
$avatar_list[$file][$avatar_row_count][$avatar_col_count] = array(
- 'file' => "$file/$sub_file",
- 'filename' => $sub_file,
+ 'file' => rawurlencode($file) . '/' . rawurlencode($sub_file),
+ 'filename' => rawurlencode($sub_file),
'name' => ucfirst(str_replace('_', ' ', preg_replace('#^(.*)\..*$#', '\1', $sub_file))),
);
$avatar_col_count++;
@@ -2365,24 +2449,9 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
global $phpbb_root_path, $config, $db, $user, $file_upload;
$error = array();
- $attribute_ary = array(
- 'group_colour' => 'string',
- 'group_rank' => 'int',
- 'group_avatar' => 'string',
- 'group_avatar_type' => 'int',
- 'group_avatar_width' => 'int',
- 'group_avatar_height' => 'int',
- 'group_receive_pm' => 'int',
- 'group_legend' => 'int',
- 'group_message_limit' => 'int',
- 'group_max_recipients' => 'int',
-
- 'group_founder_manage' => 'int',
- );
-
- // Those are group-only attributes
- $group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit', 'group_max_recipients', 'group_founder_manage');
+ // Attributes which also affect the users table
+ $user_attribute_ary = array('group_colour', 'group_rank', 'group_avatar', 'group_avatar_type', 'group_avatar_width', 'group_avatar_height');
// Check data. Limit group name length.
if (!utf8_strlen($name) || utf8_strlen($name) > 60)
@@ -2420,14 +2489,8 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
if (sizeof($group_attributes))
{
- foreach ($attribute_ary as $attribute => $_type)
- {
- if (isset($group_attributes[$attribute]))
- {
- settype($group_attributes[$attribute], $_type);
- $sql_ary[$attribute] = $group_attributes[$attribute];
- }
- }
+ // Merge them with $sql_ary to properly update the group
+ $sql_ary = array_merge($sql_ary, $group_attributes);
}
// Setting the log message before we set the group id (if group gets added)
@@ -2452,6 +2515,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
{
remove_default_avatar($group_id, $user_ary);
}
+
if (isset($sql_ary['group_rank']) && !$sql_ary['group_rank'])
{
remove_default_rank($group_id, $user_ary);
@@ -2467,6 +2531,32 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
SET group_name = '" . $db->sql_escape($sql_ary['group_name']) . "'
WHERE group_id = $group_id";
$db->sql_query($sql);
+
+ // One special case is the group skip auth setting. If this was changed we need to purge permissions for this group
+ if (isset($group_attributes['group_skip_auth']))
+ {
+ // Get users within this group...
+ $sql = 'SELECT user_id
+ FROM ' . USER_GROUP_TABLE . '
+ WHERE group_id = ' . $group_id . '
+ AND user_pending = 0';
+ $result = $db->sql_query($sql);
+
+ $user_id_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $user_id_ary[] = $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (!empty($user_id_ary))
+ {
+ global $auth;
+
+ // Clear permissions cache of relevant users
+ $auth->acl_clear_prefetch($user_id_ary);
+ }
+ }
}
else
{
@@ -2477,6 +2567,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
if (!$group_id)
{
$group_id = $db->sql_nextid();
+
if (isset($sql_ary['group_avatar_type']) && $sql_ary['group_avatar_type'] == AVATAR_UPLOAD)
{
group_correct_avatar($group_id, $sql_ary['group_avatar']);
@@ -2487,18 +2578,21 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
$sql_ary = array();
if (sizeof($group_attributes))
{
- foreach ($attribute_ary as $attribute => $_type)
+ // Go through the user attributes array, check if a group attribute matches it and then set it. ;)
+ foreach ($user_attribute_ary as $attribute)
{
- if (isset($group_attributes[$attribute]) && !in_array($attribute, $group_only_ary))
+ if (!isset($group_attributes[$attribute]))
{
- // If we are about to set an avatar, we will not overwrite user avatars if no group avatar is set...
- if (strpos($attribute, 'group_avatar') === 0 && !$group_attributes[$attribute])
- {
- continue;
- }
-
- $sql_ary[$attribute] = $group_attributes[$attribute];
+ continue;
}
+
+ // If we are about to set an avatar, we will not overwrite user avatars if no group avatar is set...
+ if (strpos($attribute, 'group_avatar') === 0 && !$group_attributes[$attribute])
+ {
+ continue;
+ }
+
+ $sql_ary[$attribute] = $group_attributes[$attribute];
}
}
@@ -2702,7 +2796,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
if ($default)
{
- group_set_user_default($group_id, $user_id_ary, $group_attributes);
+ group_user_attributes('default', $group_id, $user_id_ary, false, $group_name, $group_attributes);
}
$db->sql_transaction('commit');
@@ -2715,7 +2809,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
$group_name = get_group_name($group_id);
}
- $log = ($leader) ? 'LOG_MODS_ADDED' : 'LOG_USERS_ADDED';
+ $log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : 'LOG_USERS_ADDED');
add_log('admin', $log, $group_name, implode(', ', $username_ary));
@@ -2826,7 +2920,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
{
if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid]))
{
- remove_default_rank($gid, $sql_where_ary[$gid]);
+ remove_default_rank($group_id, $sql_where_ary[$gid]);
remove_default_avatar($group_id, $sql_where_ary[$gid]);
group_set_user_default($gid, $sql_where_ary[$gid], $default_data_ary);
}
@@ -2848,7 +2942,10 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
$log = 'LOG_GROUP_REMOVE';
- add_log('admin', $log, $group_name, implode(', ', $username_ary));
+ if ($group_name)
+ {
+ add_log('admin', $log, $group_name, implode(', ', $username_ary));
+ }
group_update_listings($group_id);
@@ -3038,6 +3135,27 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
break;
case 'default':
+ // We only set default group for approved members of the group
+ $sql = 'SELECT user_id
+ FROM ' . USER_GROUP_TABLE . "
+ WHERE group_id = $group_id
+ AND user_pending = 0
+ AND " . $db->sql_in_set('user_id', $user_id_ary);
+ $result = $db->sql_query($sql);
+
+ $user_id_ary = $username_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $user_id_ary[] = $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $result = user_get_id_name($user_id_ary, $username_ary);
+ if (!sizeof($user_id_ary) || $result !== false)
+ {
+ return 'NO_USERS';
+ }
+
$sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true);
$result = $db->sql_query($sql);
@@ -3126,7 +3244,7 @@ function group_validate_groupname($group_id, $group_name)
*/
function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false)
{
- global $db;
+ global $cache, $db;
if (empty($user_id_ary))
{
@@ -3226,6 +3344,9 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
{
group_update_listings($group_id);
}
+
+ // Because some tables/caches use usercolour-specific data we need to purge this here.
+ $cache->destroy('sql', MODERATOR_CACHE_TABLE);
}
/**
@@ -3242,7 +3363,7 @@ function get_group_name($group_id)
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if (!$row)
+ if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang)))
{
return '';
}
@@ -3385,4 +3506,77 @@ function group_update_listings($group_id)
}
}
+
+
+/**
+* Funtion to make a user leave the NEWLY_REGISTERED system group.
+* @access public
+* @param $user_id The id of the user to remove from the group
+*/
+function remove_newly_registered($user_id, $user_data = false)
+{
+ global $db;
+
+ if ($user_data === false)
+ {
+ $sql = 'SELECT *
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . $user_id;
+ $result = $db->sql_query($sql);
+ $user_row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!$user_row)
+ {
+ return false;
+ }
+ else
+ {
+ $user_data = $user_row;
+ }
+ }
+
+ if (empty($user_data['user_new']))
+ {
+ return false;
+ }
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = 'NEWLY_REGISTERED'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $db->sql_query($sql);
+ $group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+
+ if (!$group_id)
+ {
+ return false;
+ }
+
+ // We need to call group_user_del here, because this function makes sure everything is correctly changed.
+ // A downside for a call within the session handler is that the language is not set up yet - so no log entry
+ group_user_del($group_id, $user_id);
+
+ // Set user_new to 0 to let this not be triggered again
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_new = 0
+ WHERE user_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ // The new users group was the users default group?
+ if ($user_data['group_id'] == $group_id)
+ {
+ // Which group is now the users default one?
+ $sql = 'SELECT group_id
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . $user_id;
+ $result = $db->sql_query($sql);
+ $user_data['group_id'] = $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+ }
+
+ return $user_data['group_id'];
+}
+
?>
\ No newline at end of file
diff --git a/phpBB/includes/mcp/info/mcp_pm_reports.php b/phpBB/includes/mcp/info/mcp_pm_reports.php
new file mode 100644
index 0000000000..103f560597
--- /dev/null
+++ b/phpBB/includes/mcp/info/mcp_pm_reports.php
@@ -0,0 +1,39 @@
+ 'mcp_pm_reports',
+ 'title' => 'MCP_PM_REPORTS',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')),
+ 'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')),
+ 'pm_report_details' => array('title' => 'MCP_PM_REPORT_DETAILS', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index b70601b479..acb7aa4ac0 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -416,11 +416,14 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
// If the topic no longer exist, we will update the topic watch table.
// To not let it error out on users watching both topics, we just return on an error...
+ // Same for Bookmarks
$db->sql_return_on_error(true);
$db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
+ $db->sql_query('UPDATE ' . BOOKMARKS_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
$db->sql_return_on_error(false);
$db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
+ $db->sql_query('DELETE FROM ' . BOOKMARKS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
// Link to the new topic
$return_link .= (($return_link) ? '
' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '
', '');
diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php
index 05c1b796ac..50e14b9336 100644
--- a/phpBB/includes/mcp/mcp_front.php
+++ b/phpBB/includes/mcp/mcp_front.php
@@ -34,7 +34,7 @@ function mcp_front_view($id, $mode, $action)
$forum_id = request_var('f', 0);
$template->assign_var('S_SHOW_UNAPPROVED', (!empty($forum_list)) ? true : false);
-
+
if (!empty($forum_list))
{
$sql = 'SELECT COUNT(post_id) AS total
@@ -119,7 +119,12 @@ function mcp_front_view($id, $mode, $action)
$db->sql_freeresult($result);
}
+ $s_hidden_fields = build_hidden_fields(array(
+ 'redirect' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main' . (($forum_id) ? '&f=' . $forum_id : ''))
+ ));
+
$template->assign_vars(array(
+ 'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_MCP_QUEUE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue"),
));
@@ -152,6 +157,7 @@ function mcp_front_view($id, $mode, $action)
$sql = 'SELECT COUNT(r.report_id) AS total
FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p
WHERE r.post_id = p.post_id
+ AND r.pm_id = 0
AND r.report_closed = 0
AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')';
$result = $db->sql_query($sql);
@@ -181,6 +187,7 @@ function mcp_front_view($id, $mode, $action)
),
'WHERE' => 'r.post_id = p.post_id
+ AND r.pm_id = 0
AND r.report_closed = 0
AND r.reason_id = rr.reason_id
AND p.topic_id = t.topic_id
@@ -243,6 +250,96 @@ function mcp_front_view($id, $mode, $action)
}
}
+ // Latest 5 reported PMs
+ if ($module->loaded('pm_reports') && $auth->acl_getf_global('m_report'))
+ {
+ $template->assign_var('S_SHOW_PM_REPORTS', true);
+ $user->add_lang(array('ucp'));
+
+ $sql = 'SELECT COUNT(r.report_id) AS total
+ FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . ' p
+ WHERE r.post_id = 0
+ AND r.pm_id = p.msg_id
+ AND r.report_closed = 0';
+ $result = $db->sql_query($sql);
+ $total = (int) $db->sql_fetchfield('total');
+ $db->sql_freeresult($result);
+
+ if ($total)
+ {
+ include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
+
+ $sql = $db->sql_build_query('SELECT', array(
+ 'SELECT' => 'r.report_id, r.report_time, p.msg_id, p.message_subject, p.message_time, p.to_address, p.bcc_address, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id',
+
+ 'FROM' => array(
+ REPORTS_TABLE => 'r',
+ REPORTS_REASONS_TABLE => 'rr',
+ USERS_TABLE => array('u', 'u2'),
+ PRIVMSGS_TABLE => 'p'
+ ),
+
+ 'WHERE' => 'r.pm_id = p.msg_id
+ AND r.post_id = 0
+ AND r.report_closed = 0
+ AND r.reason_id = rr.reason_id
+ AND r.user_id = u.user_id
+ AND p.author_id = u2.user_id',
+
+ 'ORDER_BY' => 'p.message_time DESC'
+ ));
+ $result = $db->sql_query_limit($sql, 5);
+
+ $pm_by_id = $pm_list = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $pm_by_id[(int) $row['msg_id']] = $row;
+ $pm_list[] = (int) $row['msg_id'];
+ }
+
+ $address_list = get_recipient_strings($pm_by_id);
+
+ foreach ($pm_list as $message_id)
+ {
+ $row = $pm_by_id[$message_id];
+
+ $template->assign_block_vars('pm_report', array(
+ 'U_PM_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'r=' . $row['report_id'] . "&i=pm_reports&mode=pm_report_details"),
+
+ 'REPORTER_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']),
+ 'REPORTER' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
+ 'REPORTER_COLOUR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
+ 'U_REPORTER' => get_username_string('profile', $row['user_id'], $row['username'], $row['user_colour']),
+
+ 'PM_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['author_name'], $row['author_colour']),
+ 'PM_AUTHOR' => get_username_string('username', $row['author_id'], $row['author_name'], $row['author_colour']),
+ 'PM_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['author_name'], $row['author_colour']),
+ 'U_PM_AUTHOR' => get_username_string('profile', $row['author_id'], $row['author_name'], $row['author_colour']),
+
+ 'PM_SUBJECT' => $row['message_subject'],
+ 'REPORT_TIME' => $user->format_date($row['report_time']),
+ 'PM_TIME' => $user->format_date($row['message_time']),
+ 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]),
+ ));
+ }
+ }
+
+ if ($total == 0)
+ {
+ $template->assign_vars(array(
+ 'L_PM_REPORTS_TOTAL' => $user->lang['PM_REPORTS_ZERO_TOTAL'],
+ 'S_HAS_PM_REPORTS' => false)
+ );
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'L_PM_REPORTS_TOTAL' => ($total == 1) ? $user->lang['PM_REPORT_TOTAL'] : sprintf($user->lang['PM_REPORTS_TOTAL'], $total),
+ 'S_HAS_PM_REPORTS' => true)
+ );
+ }
+ }
+
// Latest 5 logs
if ($module->loaded('logs'))
{
diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php
index a6b1935c88..429e19b668 100644
--- a/phpBB/includes/mcp/mcp_logs.php
+++ b/phpBB/includes/mcp/mcp_logs.php
@@ -164,15 +164,18 @@ class mcp_logs
$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
+ $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
+
// Grab log data
$log_data = array();
$log_count = 0;
- view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort);
+ view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort, $keywords);
$template->assign_vars(array(
'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start),
'TOTAL' => ($log_count == 1) ? $user->lang['TOTAL_LOG'] : sprintf($user->lang['TOTAL_LOGS'], $log_count),
- 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $log_count, $config['topics_per_page'], $start),
+ 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true),
'L_TITLE' => $user->lang['MCP_LOGS'],
@@ -182,13 +185,14 @@ class mcp_logs
'S_SELECT_SORT_KEY' => $s_sort_key,
'S_SELECT_SORT_DAYS' => $s_limit_days,
'S_LOGS' => ($log_count > 0),
+ 'S_KEYWORDS' => $keywords,
)
);
foreach ($log_data as $row)
{
$data = array();
-
+
$checks = array('viewtopic', 'viewforum');
foreach ($checks as $check)
{
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index 0dfe3b0086..6c2ac0b521 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -1064,7 +1064,9 @@ function mcp_fork_topic($topic_ids)
'topic_bumper' => (int) $topic_row['topic_bumper'],
'poll_title' => (string) $topic_row['poll_title'],
'poll_start' => (int) $topic_row['poll_start'],
- 'poll_length' => (int) $topic_row['poll_length']
+ 'poll_length' => (int) $topic_row['poll_length'],
+ 'poll_max_options' => (int) $topic_row['poll_max_options'],
+ 'poll_vote_change' => (int) $topic_row['poll_vote_change'],
);
$db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
@@ -1166,8 +1168,8 @@ function mcp_fork_topic($topic_ids)
'in_message' => 0,
'is_orphan' => (int) $attach_row['is_orphan'],
'poster_id' => (int) $attach_row['poster_id'],
- 'physical_filename' => (string) basename($attach_row['physical_filename']),
- 'real_filename' => (string) basename($attach_row['real_filename']),
+ 'physical_filename' => (string) utf8_basename($attach_row['physical_filename']),
+ 'real_filename' => (string) utf8_basename($attach_row['real_filename']),
'download_count' => (int) $attach_row['download_count'],
'attach_comment' => (string) $attach_row['attach_comment'],
'extension' => (string) $attach_row['extension'],
diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php
index 7480b24a46..757860e1af 100644
--- a/phpBB/includes/mcp/mcp_notes.php
+++ b/phpBB/includes/mcp/mcp_notes.php
@@ -193,9 +193,12 @@ class mcp_notes
$sql_where = ($st) ? (time() - ($st * 86400)) : 0;
$sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC');
+ $keywords = utf8_normalize_nfc(request_var('keywords', '', true));
+ $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
+
$log_data = array();
$log_count = 0;
- view_log('user', $log_data, $log_count, $config['posts_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort);
+ view_log('user', $log_data, $log_count, $config['posts_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort, $keywords);
if ($log_count)
{
@@ -219,11 +222,12 @@ class mcp_notes
'S_SELECT_SORT_DIR' => $s_sort_dir,
'S_SELECT_SORT_KEY' => $s_sort_key,
'S_SELECT_SORT_DAYS' => $s_limit_days,
+ 'S_KEYWORDS' => $keywords,
'L_TITLE' => $user->lang['MCP_NOTES_USER'],
'PAGE_NUMBER' => on_page($log_count, $config['posts_per_page'], $start),
- 'PAGINATION' => generate_pagination($this->u_action . "&st=$st&sk=$sk&sd=$sd", $log_count, $config['posts_per_page'], $start),
+ 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true),
'TOTAL_REPORTS' => ($log_count == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $log_count),
'RANK_TITLE' => $rank_title,
diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php
new file mode 100644
index 0000000000..72f77fae7c
--- /dev/null
+++ b/phpBB/includes/mcp/mcp_pm_reports.php
@@ -0,0 +1,323 @@
+p_master = &$p_master;
+ }
+
+ function main($id, $mode)
+ {
+ global $auth, $db, $user, $template, $cache;
+ global $config, $phpbb_root_path, $phpEx, $action;
+
+ include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
+ include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
+
+ $start = request_var('start', 0);
+
+ $this->page_title = 'MCP_PM_REPORTS';
+
+ switch ($action)
+ {
+ case 'close':
+ case 'delete':
+ include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
+
+ $report_id_list = request_var('report_id_list', array(0));
+
+ if (!sizeof($report_id_list))
+ {
+ trigger_error('NO_REPORT_SELECTED');
+ }
+
+ if (!function_exists('close_report'))
+ {
+ include($phpbb_root_path . 'includes/mcp/mcp_reports.' . $phpEx);
+ }
+
+ close_report($report_id_list, $mode, $action, true);
+
+ break;
+ }
+
+ switch ($mode)
+ {
+ case 'pm_report_details':
+
+ $user->add_lang(array('posting', 'viewforum', 'viewtopic', 'ucp'));
+
+ $report_id = request_var('r', 0);
+
+ $sql = 'SELECT r.pm_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour
+ FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u
+ WHERE r.report_id = ' . $report_id . '
+ AND rr.reason_id = r.reason_id
+ AND r.user_id = u.user_id
+ AND r.post_id = 0
+ ORDER BY report_closed ASC';
+ $result = $db->sql_query_limit($sql, 1);
+ $report = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if (!$report_id || !$report)
+ {
+ trigger_error('NO_REPORT');
+ }
+
+ $pm_id = $report['pm_id'];
+ $report_id = $report['report_id'];
+
+ $pm_info = get_pm_data(array($pm_id));
+
+ if (!sizeof($pm_info))
+ {
+ trigger_error('NO_REPORT_SELECTED');
+ }
+
+ $pm_info = $pm_info[$pm_id];
+
+ write_pm_addresses(array('to' => $pm_info['to_address'], 'bcc' => $pm_info['bcc_address']), (int) $pm_info['author_id']);
+
+ $reason = array('title' => $report['reason_title'], 'description' => $report['reason_description']);
+ if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])]))
+ {
+ $reason['description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])];
+ $reason['title'] = $user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])];
+ }
+
+ // Process message, leave it uncensored
+ $message = $pm_info['message_text'];
+
+ if ($pm_info['bbcode_bitfield'])
+ {
+ include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
+ $bbcode = new bbcode($pm_info['bbcode_bitfield']);
+ $bbcode->bbcode_second_pass($message, $pm_info['bbcode_uid'], $pm_info['bbcode_bitfield']);
+ }
+
+ $message = bbcode_nl2br($message);
+ $message = smiley_text($message);
+
+ if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download'))
+ {
+ $sql = 'SELECT *
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE post_msg_id = ' . $pm_id . '
+ AND in_message = 1
+ ORDER BY filetime DESC';
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $attachments[] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($attachments))
+ {
+ $update_count = array();
+ parse_attachments(0, $message, $attachments, $update_count);
+ }
+
+ // Display not already displayed Attachments for this post, we already parsed them. ;)
+ if (!empty($attachments))
+ {
+ $template->assign_var('S_HAS_ATTACHMENTS', true);
+
+ foreach ($attachments as $attachment)
+ {
+ $template->assign_block_vars('attachment', array(
+ 'DISPLAY_ATTACHMENT' => $attachment)
+ );
+ }
+ }
+ }
+
+ $template->assign_vars(array(
+ 'S_MCP_REPORT' => true,
+ 'S_PM' => true,
+ 'S_CLOSE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=pm_reports&mode=pm_report_details&r=' . $report_id),
+ 'S_CAN_VIEWIP' => $auth->acl_getf_global('m_info'),
+ 'S_POST_REPORTED' => $pm_info['message_reported'],
+ 'S_USER_NOTES' => true,
+
+ 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=pm_reports&mode=pm_report_details&r=' . $report_id),
+ 'U_MCP_REPORTER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $report['user_id']),
+ 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $pm_info['author_id']),
+ 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '',
+ 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $pm_info['author_id']) : '',
+
+ 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']),
+ 'MINI_POST_IMG' => $user->img('icon_post_target', 'POST'),
+
+ 'RETURN_REPORTS' => sprintf($user->lang['RETURN_REPORTS'], '
', ''),
+ 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']),
+ 'REPORT_DATE' => $user->format_date($report['report_time']),
+ 'REPORT_ID' => $report_id,
+ 'REPORT_REASON_TITLE' => $reason['title'],
+ 'REPORT_REASON_DESCRIPTION' => $reason['description'],
+ 'REPORT_TEXT' => $report['report_text'],
+
+ 'POST_AUTHOR_FULL' => get_username_string('full', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']),
+ 'POST_AUTHOR_COLOUR' => get_username_string('colour', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']),
+ 'POST_AUTHOR' => get_username_string('username', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']),
+ 'U_POST_AUTHOR' => get_username_string('profile', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']),
+
+ 'REPORTER_FULL' => get_username_string('full', $report['user_id'], $report['username'], $report['user_colour']),
+ 'REPORTER_COLOUR' => get_username_string('colour', $report['user_id'], $report['username'], $report['user_colour']),
+ 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']),
+ 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']),
+
+ 'POST_PREVIEW' => $message,
+ 'POST_SUBJECT' => ($pm_info['message_subject']) ? $pm_info['message_subject'] : $user->lang['NO_SUBJECT'],
+ 'POST_DATE' => $user->format_date($pm_info['message_time']),
+ 'POST_IP' => $pm_info['author_ip'],
+ 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && request_var('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '',
+ 'POST_ID' => $pm_info['msg_id'],
+
+ 'U_LOOKUP_IP' => ($auth->acl_getf_global('m_info')) ? $this->u_action . '&r=' . $report_id . '&pm=' . $pm_id . '&lookup=' . $pm_info['author_ip'] . '#ip' : '',
+ ));
+
+ $this->tpl_name = 'mcp_post';
+
+ break;
+
+ case 'pm_reports':
+ case 'pm_reports_closed':
+ $user->add_lang(array('ucp'));
+
+ $sort_days = $total = 0;
+ $sort_key = $sort_dir = '';
+ $sort_by_sql = $sort_order_sql = array();
+ mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total);
+
+ $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : '';
+
+ if ($mode == 'pm_reports')
+ {
+ $report_state = 'p.message_reported = 1 AND r.report_closed = 0';
+ }
+ else
+ {
+ $report_state = 'r.report_closed = 1';
+ }
+
+ $sql = 'SELECT r.report_id
+ FROM ' . PRIVMSGS_TABLE . ' p, ' . REPORTS_TABLE . ' r ' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . (($sort_order_sql[0] == 'r') ? ', ' . USERS_TABLE . ' ru' : '') . "
+ WHERE $report_state
+ AND r.pm_id = p.msg_id
+ " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.author_id' : '') . '
+ ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = r.user_id' : '') . "
+ AND r.post_id = 0
+ $limit_time_sql
+ ORDER BY $sort_order_sql";
+ $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start);
+
+ $i = 0;
+ $report_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $report_ids[] = $row['report_id'];
+ $row_num[$row['report_id']] = $i++;
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($report_ids))
+ {
+ $sql = 'SELECT p.*, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id
+ FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru
+ WHERE ' . $db->sql_in_set('r.report_id', $report_ids) . "
+ AND r.pm_id = p.msg_id
+ AND p.author_id = u.user_id
+ AND ru.user_id = r.user_id
+ ORDER BY $sort_order_sql";
+ $result = $db->sql_query($sql);
+
+ $pm_list = $pm_by_id = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $pm_by_id[(int) $row['msg_id']] = $row;
+ $pm_list[] = (int) $row['msg_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($pm_list))
+ {
+ $address_list = get_recipient_strings($pm_by_id);
+
+ foreach ($pm_list as $message_id)
+ {
+ $row = $pm_by_id[$message_id];
+ $template->assign_block_vars('postrow', array(
+ 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=pm_reports&mode=pm_report_details&r={$row['report_id']}"),
+
+ 'PM_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['username'], $row['user_colour']),
+ 'PM_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['username'], $row['user_colour']),
+ 'PM_AUTHOR' => get_username_string('username', $row['author_id'], $row['username'], $row['user_colour']),
+ 'U_PM_AUTHOR' => get_username_string('profile', $row['author_id'], $row['username'], $row['user_colour']),
+
+ 'REPORTER_FULL' => get_username_string('full', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']),
+ 'REPORTER_COLOUR' => get_username_string('colour', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']),
+ 'REPORTER' => get_username_string('username', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']),
+ 'U_REPORTER' => get_username_string('profile', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']),
+
+ 'PM_SUBJECT' => ($row['message_subject']) ? $row['message_subject'] : $user->lang['NO_SUBJECT'],
+ 'PM_TIME' => $user->format_date($row['message_time']),
+ 'REPORT_ID' => $row['report_id'],
+ 'REPORT_TIME' => $user->format_date($row['report_time']),
+
+ 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]),
+ ));
+ }
+ }
+ }
+
+ // Now display the page
+ $template->assign_vars(array(
+ 'L_EXPLAIN' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_PM_REPORTS_CLOSED_EXPLAIN'],
+ 'L_TITLE' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN'] : $user->lang['MCP_PM_REPORTS_CLOSED'],
+
+ 'S_PM' => true,
+ 'S_MCP_ACTION' => $this->u_action,
+ 'S_CLOSED' => ($mode == 'pm_reports_closed') ? true : false,
+
+ 'PAGINATION' => generate_pagination($this->u_action . "&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start),
+ 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start),
+ 'TOTAL' => $total,
+ 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total),
+ )
+ );
+
+ $this->tpl_name = 'mcp_reports';
+ break;
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index 6209a27bf7..3783aadab5 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -491,11 +491,9 @@ function approve_post($post_id_list, $id, $mode)
// If Post -> total_posts = total_posts+1, forum_posts = forum_posts+1, topic_replies = topic_replies+1
$total_topics = $total_posts = 0;
- $forum_topics_posts = $topic_approve_sql = $topic_replies_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array();
+ $topic_approve_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array();
$user_posts_sql = $post_approved_list = array();
- $update_forum_information = false;
-
foreach ($post_info as $post_id => $post_data)
{
if ($post_data['post_approved'])
@@ -523,16 +521,7 @@ function approve_post($post_id_list, $id, $mode)
{
if ($post_data['forum_id'])
{
- if (!isset($forum_topics_posts[$post_data['forum_id']]))
- {
- $forum_topics_posts[$post_data['forum_id']] = array(
- 'forum_posts' => 0,
- 'forum_topics' => 0
- );
- }
-
$total_topics++;
- $forum_topics_posts[$post_data['forum_id']]['forum_topics']++;
}
$topic_approve_sql[] = $post_data['topic_id'];
@@ -553,45 +542,21 @@ function approve_post($post_id_list, $id, $mode)
);
}
- if ($post_data['topic_replies_real'] > 0)
- {
- if (!isset($topic_replies_sql[$post_data['topic_id']]))
- {
- $topic_replies_sql[$post_data['topic_id']] = 0;
- }
- $topic_replies_sql[$post_data['topic_id']]++;
- }
-
if ($post_data['forum_id'])
{
- if (!isset($forum_topics_posts[$post_data['forum_id']]))
- {
- $forum_topics_posts[$post_data['forum_id']] = array(
- 'forum_posts' => 0,
- 'forum_topics' => 0
- );
- }
-
$total_posts++;
- $forum_topics_posts[$post_data['forum_id']]['forum_posts']++;
// Increment by topic_replies if we approve a topic...
// This works because we do not adjust the topic_replies when re-approving a topic after an edit.
if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_replies'])
{
$total_posts += $post_data['topic_replies'];
- $forum_topics_posts[$post_data['forum_id']]['forum_posts'] += $post_data['topic_replies'];
}
}
$post_approve_sql[] = $post_id;
-
- // If the post is newer than the last post information stored we need to update the forum information
- if ($post_data['post_time'] >= $post_data['forum_last_post_time'])
- {
- $update_forum_information = true;
- }
}
+
$post_id_list = array_values(array_diff($post_id_list, $post_approved_list));
for ($i = 0, $size = sizeof($post_approved_list); $i < $size; $i++)
{
@@ -614,37 +579,13 @@ function approve_post($post_id_list, $id, $mode)
$db->sql_query($sql);
}
+ unset($topic_approve_sql, $post_approve_sql);
+
foreach ($approve_log as $log_data)
{
add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_APPROVED' : 'LOG_POST_APPROVED', $log_data['post_subject']);
}
- if (sizeof($topic_replies_sql))
- {
- foreach ($topic_replies_sql as $topic_id => $num_replies)
- {
- $sql = 'UPDATE ' . TOPICS_TABLE . "
- SET topic_replies = topic_replies + $num_replies
- WHERE topic_id = $topic_id";
- $db->sql_query($sql);
- }
- }
-
- if (sizeof($forum_topics_posts))
- {
- foreach ($forum_topics_posts as $forum_id => $row)
- {
- $sql = 'UPDATE ' . FORUMS_TABLE . '
- SET ';
- $sql .= ($row['forum_topics']) ? "forum_topics = forum_topics + {$row['forum_topics']}" : '';
- $sql .= ($row['forum_topics'] && $row['forum_posts']) ? ', ' : '';
- $sql .= ($row['forum_posts']) ? "forum_posts = forum_posts + {$row['forum_posts']}" : '';
- $sql .= " WHERE forum_id = $forum_id";
-
- $db->sql_query($sql);
- }
- }
-
if (sizeof($user_posts_sql))
{
// Try to minimize the query count by merging users with the same post count additions
@@ -673,14 +614,9 @@ function approve_post($post_id_list, $id, $mode)
{
set_config_count('num_posts', $total_posts, true);
}
- unset($topic_approve_sql, $topic_replies_sql, $post_approve_sql);
- update_post_information('topic', array_keys($topic_id_list));
-
- if ($update_forum_information)
- {
- update_post_information('forum', array_keys($forum_id_list));
- }
+ sync('topic', 'topic_id', array_keys($topic_id_list), true);
+ sync('forum', 'forum_id', array_keys($forum_id_list), true, true);
unset($topic_id_list, $forum_id_list);
$messenger = new messenger();
@@ -859,89 +795,63 @@ function disapprove_post($post_id_list, $id, $mode)
if (confirm_box(true))
{
+ $disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array();
+ $topic_replies_real = $post_disapprove_list = array();
- // If Topic -> forum_topics_real -= 1
- // If Post -> topic_replies_real -= 1
-
- $num_disapproved = 0;
- $forum_topics_real = $topic_id_list = $forum_id_list = $topic_replies_real_sql = $post_disapprove_sql = $disapprove_log = array();
-
+ // Build a list of posts to be unapproved and get the related topics real replies count
foreach ($post_info as $post_id => $post_data)
{
- $topic_id_list[$post_data['topic_id']] = 1;
-
- if ($post_data['forum_id'])
+ $post_disapprove_list[$post_id] = $post_data['topic_id'];
+ if (!isset($topic_replies_real[$post_data['topic_id']]))
{
- $forum_id_list[$post_data['forum_id']] = 1;
+ $topic_replies_real[$post_data['topic_id']] = $post_data['topic_replies_real'];
}
+ }
- // Topic or Post. ;)
- /**
- * @todo this probably is a different method than the one used by delete_posts, does this cause counter inconsistency?
- */
- if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_last_post_id'] == $post_id)
+ // Now we build the log array
+ foreach ($post_disapprove_list as $post_id => $topic_id)
+ {
+ // If the count of disapproved posts for the topic is greater
+ // than topic's real replies count, the whole topic is disapproved/deleted
+ if (sizeof(array_keys($post_disapprove_list, $topic_id)) > $topic_replies_real[$topic_id])
{
- if ($post_data['forum_id'])
+ // Don't write the log more than once for every topic
+ if (!isset($disapprove_log_topics[$topic_id]))
{
- if (!isset($forum_topics_real[$post_data['forum_id']]))
- {
- $forum_topics_real[$post_data['forum_id']] = 0;
- }
- $forum_topics_real[$post_data['forum_id']]++;
- $num_disapproved++;
+ // Build disapproved topics log
+ $disapprove_log_topics[$topic_id] = array(
+ 'type' => 'topic',
+ 'post_subject' => $post_info[$post_id]['topic_title'],
+ 'forum_id' => $post_info[$post_id]['forum_id'],
+ 'topic_id' => 0, // useless to log a topic id, as it will be deleted
+ );
}
-
- $disapprove_log[] = array(
- 'type' => 'topic',
- 'post_subject' => $post_data['post_subject'],
- 'forum_id' => $post_data['forum_id'],
- 'topic_id' => 0, // useless to log a topic id, as it will be deleted
- );
}
else
{
- if (!isset($topic_replies_real_sql[$post_data['topic_id']]))
- {
- $topic_replies_real_sql[$post_data['topic_id']] = 0;
- }
- $topic_replies_real_sql[$post_data['topic_id']]++;
-
- $disapprove_log[] = array(
+ // Build disapproved posts log
+ $disapprove_log_posts[] = array(
'type' => 'post',
- 'post_subject' => $post_data['post_subject'],
- 'forum_id' => $post_data['forum_id'],
- 'topic_id' => $post_data['topic_id'],
+ 'post_subject' => $post_info[$post_id]['post_subject'],
+ 'forum_id' => $post_info[$post_id]['forum_id'],
+ 'topic_id' => $post_info[$post_id]['topic_id'],
);
- }
- $post_disapprove_sql[] = $post_id;
- }
-
- unset($post_data);
-
- if (sizeof($forum_topics_real))
- {
- foreach ($forum_topics_real as $forum_id => $topics_real)
- {
- $sql = 'UPDATE ' . FORUMS_TABLE . "
- SET forum_topics_real = forum_topics_real - $topics_real
- WHERE forum_id = $forum_id";
- $db->sql_query($sql);
}
}
- if (sizeof($topic_replies_real_sql))
- {
- foreach ($topic_replies_real_sql as $topic_id => $num_replies)
- {
- $sql = 'UPDATE ' . TOPICS_TABLE . "
- SET topic_replies_real = topic_replies_real - $num_replies
- WHERE topic_id = $topic_id";
- $db->sql_query($sql);
- }
- }
+ // Get disapproved posts/topics counts separately
+ $num_disapproved_topics = sizeof($disapprove_log_topics);
+ $num_disapproved_posts = sizeof($disapprove_log_posts);
- if (sizeof($post_disapprove_sql))
+ // Build the whole log
+ $disapprove_log = array_merge($disapprove_log_topics, $disapprove_log_posts);
+
+ // Unset unneeded arrays
+ unset($post_data, $disapprove_log_topics, $disapprove_log_posts);
+
+ // Let's do the job - delete disapproved posts
+ if (sizeof($post_disapprove_list))
{
if (!function_exists('delete_posts'))
{
@@ -949,22 +859,15 @@ function disapprove_post($post_id_list, $id, $mode)
}
// We do not check for permissions here, because the moderator allowed approval/disapproval should be allowed to delete the disapproved posts
- delete_posts('post_id', $post_disapprove_sql);
+ // Note: function delete_posts triggers related forums/topics sync,
+ // so we don't need to call update_post_information later and to adjust real topic replies or forum topics count manually
+ delete_posts('post_id', array_keys($post_disapprove_list));
foreach ($disapprove_log as $log_data)
{
add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED', $log_data['post_subject'], $disapprove_reason);
}
}
- unset($post_disapprove_sql, $topic_replies_real_sql);
-
- update_post_information('topic', array_keys($topic_id_list));
-
- if (sizeof($forum_id_list))
- {
- update_post_information('forum', array_keys($forum_id_list));
- }
- unset($topic_id_list, $forum_id_list);
$messenger = new messenger();
@@ -993,7 +896,7 @@ function disapprove_post($post_id_list, $id, $mode)
{
// Load up the language pack
$lang = array();
- @include($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx);
+ @include($phpbb_root_path . '/language/' . basename($post_data['user_lang']) . '/mcp.' . $phpEx);
// If we find the reason in this language pack use it
if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]))
@@ -1032,13 +935,13 @@ function disapprove_post($post_id_list, $id, $mode)
$messenger->save_queue();
- if (sizeof($forum_topics_real))
+ if ($num_disapproved_topics)
{
- $success_msg = ($num_disapproved == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS';
+ $success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS';
}
else
{
- $success_msg = (sizeof($post_id_list) == 1) ? 'POST_DISAPPROVED_SUCCESS' : 'POSTS_DISAPPROVED_SUCCESS';
+ $success_msg = ($num_disapproved_posts == 1) ? 'POST_DISAPPROVED_SUCCESS' : 'POSTS_DISAPPROVED_SUCCESS';
}
}
else
diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php
index 27d841c81b..270b0055d9 100644
--- a/phpBB/includes/mcp/mcp_reports.php
+++ b/phpBB/includes/mcp/mcp_reports.php
@@ -77,6 +77,7 @@ class mcp_reports
WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . '
AND rr.reason_id = r.reason_id
AND r.user_id = u.user_id
+ AND r.pm_id = 0
ORDER BY report_closed ASC';
$result = $db->sql_query_limit($sql, 1);
$report = $db->sql_fetchrow($result);
@@ -149,13 +150,11 @@ class mcp_reports
if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id']))
{
- $extensions = $cache->obtain_attach_extensions($post_info['forum_id']);
-
$sql = 'SELECT *
FROM ' . ATTACHMENTS_TABLE . '
WHERE post_msg_id = ' . $post_id . '
AND in_message = 0
- ORDER BY filetime DESC, post_msg_id ASC';
+ ORDER BY filetime DESC';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -258,7 +257,7 @@ class mcp_reports
}
unset($forum_list_read);
- if ($topic_id && $forum_id)
+ if ($topic_id)
{
$topic_info = get_topic_data(array($topic_id));
@@ -267,12 +266,15 @@ class mcp_reports
trigger_error('TOPIC_NOT_EXIST');
}
- $topic_info = $topic_info[$topic_id];
- $forum_id = $topic_info['forum_id'];
- }
- else if ($topic_id && !$forum_id)
- {
- $topic_id = 0;
+ if ($forum_id != $topic_info[$topic_id]['forum_id'])
+ {
+ $topic_id = 0;
+ }
+ else
+ {
+ $topic_info = $topic_info[$topic_id];
+ $forum_id = (int) $topic_info['forum_id'];
+ }
}
$forum_list = array();
@@ -329,7 +331,7 @@ class mcp_reports
mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id);
$forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total;
- $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : '';
+ $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : '';
if ($mode == 'reports')
{
@@ -346,9 +348,10 @@ class mcp_reports
$report_state
AND r.post_id = p.post_id
" . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . '
- ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = p.poster_id' : '') . '
+ ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = r.user_id' : '') . '
' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . "
AND t.topic_id = p.topic_id
+ AND r.pm_id = 0
$limit_time_sql
ORDER BY $sort_order_sql";
$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start);
@@ -371,6 +374,7 @@ class mcp_reports
AND r.post_id = p.post_id
AND u.user_id = p.poster_id
AND ru.user_id = r.user_id
+ AND r.pm_id = 0
ORDER BY ' . $sort_order_sql;
$result = $db->sql_query($sql);
@@ -438,35 +442,54 @@ class mcp_reports
/**
* Closes a report
*/
-function close_report($report_id_list, $mode, $action)
+function close_report($report_id_list, $mode, $action, $pm = false)
{
- global $db, $template, $user, $config;
+ global $db, $template, $user, $config, $auth;
global $phpEx, $phpbb_root_path;
- $sql = 'SELECT r.post_id
- FROM ' . REPORTS_TABLE . ' r
- WHERE ' . $db->sql_in_set('r.report_id', $report_id_list);
+ $pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 ';
+ $id_column = ($pm) ? 'pm_id' : 'post_id';
+ $module = ($pm) ? 'pm_reports' : 'reports';
+ $pm_prefix = ($pm) ? 'PM_' : '';
+
+ $sql = "SELECT r.$id_column
+ FROM " . REPORTS_TABLE . ' r
+ WHERE ' . $db->sql_in_set('r.report_id', $report_id_list) . $pm_where;
$result = $db->sql_query($sql);
$post_id_list = array();
while ($row = $db->sql_fetchrow($result))
{
- $post_id_list[] = $row['post_id'];
+ $post_id_list[] = $row[$id_column];
}
$post_id_list = array_unique($post_id_list);
- if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report')))
+ if ($pm)
{
- trigger_error('NOT_AUTHORISED');
+ if (!$auth->acl_getf_global('m_report'))
+ {
+ trigger_error('NOT_AUTHORISED');
+ }
+ }
+ else
+ {
+ if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report')))
+ {
+ trigger_error('NOT_AUTHORISED');
+ }
}
if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false)
{
$redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=reports');
}
+ elseif ($action == 'delete' && strpos($user->data['session_page'], 'mode=pm_report_details') !== false)
+ {
+ $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=pm_reports');
+ }
else if ($action == 'close' && !request_var('r', 0))
{
- $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=reports');
+ $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=' . $module);
}
else
{
@@ -477,7 +500,7 @@ function close_report($report_id_list, $mode, $action)
$topic_ids = array();
$s_hidden_fields = build_hidden_fields(array(
- 'i' => 'reports',
+ 'i' => $module,
'mode' => $mode,
'report_id_list' => $report_id_list,
'action' => $action,
@@ -486,13 +509,13 @@ function close_report($report_id_list, $mode, $action)
if (confirm_box(true))
{
- $post_info = get_post_data($post_id_list, 'm_report');
+ $post_info = ($pm) ? get_pm_data($post_id_list) : get_post_data($post_id_list, 'm_report');
- $sql = 'SELECT r.report_id, r.post_id, r.report_closed, r.user_id, r.user_notify, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type
- FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u
+ $sql = "SELECT r.report_id, r.$id_column, r.report_closed, r.user_id, r.user_notify, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type
+ FROM " . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u
WHERE ' . $db->sql_in_set('r.report_id', $report_id_list) . '
' . (($action == 'close') ? 'AND r.report_closed = 0' : '') . '
- AND r.user_id = u.user_id';
+ AND r.user_id = u.user_id' . $pm_where;
$result = $db->sql_query($sql);
$reports = $close_report_posts = $close_report_topics = $notify_reporters = $report_id_list = array();
@@ -503,8 +526,12 @@ function close_report($report_id_list, $mode, $action)
if (!$report['report_closed'])
{
- $close_report_posts[] = $report['post_id'];
- $close_report_topics[] = $post_info[$report['post_id']]['topic_id'];
+ $close_report_posts[] = $report[$id_column];
+
+ if (!$pm)
+ {
+ $close_report_topics[] = $post_info[$report['post_id']]['topic_id'];
+ }
}
if ($report['user_notify'] && !$report['report_closed'])
@@ -519,7 +546,7 @@ function close_report($report_id_list, $mode, $action)
$close_report_posts = array_unique($close_report_posts);
$close_report_topics = array_unique($close_report_topics);
- if (sizeof($close_report_posts))
+ if (!$pm && sizeof($close_report_posts))
{
// Get a list of topics that still contain reported posts
$sql = 'SELECT DISTINCT topic_id
@@ -558,18 +585,33 @@ function close_report($report_id_list, $mode, $action)
if (sizeof($close_report_posts))
{
- $sql = 'UPDATE ' . POSTS_TABLE . '
- SET post_reported = 0
- WHERE ' . $db->sql_in_set('post_id', $close_report_posts);
- $db->sql_query($sql);
-
- if (sizeof($close_report_topics))
+ if ($pm)
{
- $sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_reported = 0
- WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . '
- OR ' . $db->sql_in_set('topic_moved_id', $close_report_topics);
+ $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
+ SET message_reported = 0
+ WHERE ' . $db->sql_in_set('msg_id', $close_report_posts);
$db->sql_query($sql);
+
+ if ($action == 'delete')
+ {echo "aha";
+ delete_pm(ANONYMOUS, $close_report_posts, PRIVMSGS_INBOX);
+ }
+ }
+ else
+ {
+ $sql = 'UPDATE ' . POSTS_TABLE . '
+ SET post_reported = 0
+ WHERE ' . $db->sql_in_set('post_id', $close_report_posts);
+ $db->sql_query($sql);
+
+ if (sizeof($close_report_topics))
+ {
+ $sql = 'UPDATE ' . TOPICS_TABLE . '
+ SET topic_reported = 0
+ WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . '
+ OR ' . $db->sql_in_set('topic_moved_id', $close_report_topics);
+ $db->sql_query($sql);
+ }
}
}
@@ -579,7 +621,14 @@ function close_report($report_id_list, $mode, $action)
foreach ($reports as $report)
{
- add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']);
+ if ($pm)
+ {
+ add_log('mod', 0, 0, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', $post_info[$report['pm_id']]['message_subject']);
+ }
+ else
+ {
+ add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']);
+ }
}
$messenger = new messenger();
@@ -594,39 +643,53 @@ function close_report($report_id_list, $mode, $action)
continue;
}
- $post_id = $reporter['post_id'];
+ $post_id = $reporter[$id_column];
- $messenger->template('report_' . $action . 'd', $reporter['user_lang']);
+ $messenger->template((($pm) ? 'pm_report_' : 'report_') . $action . 'd', $reporter['user_lang']);
$messenger->to($reporter['user_email'], $reporter['username']);
$messenger->im($reporter['user_jabber'], $reporter['username']);
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($reporter['username']),
- 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
- 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])),
- 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title'])))
- );
+ if ($pm)
+ {
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($reporter['username']),
+ 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
+ 'PM_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['message_subject'])),
+ ));
+ }
+ else
+ {
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($reporter['username']),
+ 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title'])))
+ );
+ }
$messenger->send($reporter['user_notify_type']);
}
}
- foreach ($post_info as $post)
+ if (!$pm)
{
- $forum_ids[$post['forum_id']] = $post['forum_id'];
- $topic_ids[$post['topic_id']] = $post['topic_id'];
+ foreach ($post_info as $post)
+ {
+ $forum_ids[$post['forum_id']] = $post['forum_id'];
+ $topic_ids[$post['topic_id']] = $post['topic_id'];
+ }
}
-
+
unset($notify_reporters, $post_info, $reports);
$messenger->save_queue();
- $success_msg = (sizeof($report_id_list) == 1) ? 'REPORT_' . strtoupper($action) . 'D_SUCCESS' : 'REPORTS_' . strtoupper($action) . 'D_SUCCESS';
+ $success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS';
}
else
{
- confirm_box(false, $user->lang[strtoupper($action) . '_REPORT' . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields);
+ confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields);
}
$redirect = request_var('redirect', "index.$phpEx");
@@ -639,15 +702,21 @@ function close_report($report_id_list, $mode, $action)
else
{
meta_refresh(3, $redirect);
+
$return_forum = '';
- if (sizeof($forum_ids == 1))
- {
- $return_forum = sprintf($user->lang['RETURN_FORUM'], '
', '') . '
';
- }
$return_topic = '';
- if (sizeof($topic_ids == 1))
+
+ if (!$pm)
{
- $return_topic = sprintf($user->lang['RETURN_TOPIC'], '
', '') . '
';
+ if (sizeof($forum_ids) === 1)
+ {
+ $return_forum = sprintf($user->lang['RETURN_FORUM'], '
', '') . '
';
+ }
+
+ if (sizeof($topic_ids) === 1)
+ {
+ $return_topic = sprintf($user->lang['RETURN_TOPIC'], '
', '') . '
';
+ }
}
trigger_error($user->lang[$success_msg] . '
' . $return_forum . $return_topic . sprintf($user->lang['RETURN_PAGE'], "
", ''));
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 576d20b466..e73cccce1e 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -301,8 +301,9 @@ function mcp_topic_view($id, $mode, $action)
'POSTS_PER_PAGE' => $posts_per_page,
'ACTION' => $action,
- 'REPORTED_IMG' => $user->img('icon_topic_reported', 'POST_REPORTED', false, true),
- 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED', false, true),
+ 'REPORTED_IMG' => $user->img('icon_topic_reported', 'POST_REPORTED'),
+ 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'),
+ 'INFO_IMG' => $user->img('icon_post_info', 'VIEW_INFO'),
'S_MCP_ACTION' => "$url&i=$id&mode=$mode&action=$action&start=$start",
'S_FORUM_SELECT' => ($to_forum_id) ? make_forum_select($to_forum_id, false, false, true, true, true) : make_forum_select($topic_info['forum_id'], false, false, true, true, true),
@@ -503,6 +504,45 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
// Update forum statistics
set_config_count('num_topics', 1, true);
+ // Add new topic to bookmarks
+ $bookmarks = array();
+ $sql = 'SELECT user_id
+ FROM ' . BOOKMARKS_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $bookmarks[] = array(
+ 'user_id' => (int) $row['user_id'],
+ 'topic_id' => $to_topic_id,
+ );
+ }
+ $db->sql_freeresult($result);
+ if (sizeof($bookmarks))
+ {
+ $db->sql_multi_insert(BOOKMARKS_TABLE, $bookmarks);
+ }
+
+ // Add new topic to watch-list
+ $notifications = array();
+ $sql = 'SELECT user_id, notify_status
+ FROM ' . TOPICS_WATCH_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $notifications[] = array(
+ 'user_id' => (int) $row['user_id'],
+ 'topic_id' => $to_topic_id,
+ 'notify_status' => (int) $row['notify_status'],
+ );
+ }
+ $db->sql_freeresult($result);
+ if (sizeof($notifications))
+ {
+ $db->sql_multi_insert(TOPICS_WATCH_TABLE, $notifications);
+ }
+
// Link back to both topics
$return_link = sprintf($user->lang['RETURN_TOPIC'], '
', '') . '
' . sprintf($user->lang['RETURN_NEW_TOPIC'], '
', '');
}
@@ -596,17 +636,65 @@ function merge_posts($topic_id, $to_topic_id)
if ($row)
{
+ // Add new topic to bookmarks
+ $bookmarks = array();
+ $sql = 'SELECT user_id
+ FROM ' . BOOKMARKS_TABLE . '
+ WHERE topic_id = ' . (int) $topic_id;
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $bookmarks[] = array(
+ 'user_id' => (int) $row['user_id'],
+ 'topic_id' => (int) $to_topic_id,
+ );
+ }
+ $db->sql_freeresult($result);
+ if (sizeof($bookmarks))
+ {
+ // To not let it error out on users, who already bookmarked the topic, we just return on an error...
+ $db->sql_return_on_error(true);
+ $db->sql_multi_insert(BOOKMARKS_TABLE, $bookmarks);
+ $db->sql_return_on_error(false);
+ }
+
+ // Add new topic to notifications
+ $notifications = array();
+ $sql = 'SELECT user_id, notify_status
+ FROM ' . TOPICS_WATCH_TABLE . '
+ WHERE topic_id = ' . (int) $topic_id;
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $notifications[] = array(
+ 'user_id' => (int) $row['user_id'],
+ 'topic_id' => (int) $to_topic_id,
+ 'notify_status' => (int) $row['notify_status'],
+ );
+ }
+ $db->sql_freeresult($result);
+ if (sizeof($notifications))
+ {
+ // To not let it error out on users, who already watch the topic, we just return on an error...
+ $db->sql_return_on_error(true);
+ $db->sql_multi_insert(TOPICS_WATCH_TABLE, $notifications);
+ $db->sql_return_on_error(false);
+ }
+
$return_link .= sprintf($user->lang['RETURN_TOPIC'], '
', '');
}
else
{
// If the topic no longer exist, we will update the topic watch table.
// To not let it error out on users watching both topics, we just return on an error...
+ // Same for bookmarks
$db->sql_return_on_error(true);
$db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id);
+ $db->sql_query('UPDATE ' . BOOKMARKS_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id);
$db->sql_return_on_error(false);
$db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id);
+ $db->sql_query('DELETE FROM ' . BOOKMARKS_TABLE . ' WHERE topic_id = ' . (int) $topic_id);
}
// Link to the new topic
diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php
index 4ce67e5f9b..63e5b19155 100644
--- a/phpBB/includes/mcp/mcp_warn.php
+++ b/phpBB/includes/mcp/mcp_warn.php
@@ -204,7 +204,7 @@ class mcp_warn
$sql = 'SELECT u.*, p.*
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
- WHERE post_id = $post_id
+ WHERE p.post_id = $post_id
AND u.user_id = p.poster_id";
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php
index ab6fc3f4f3..72c101f7a3 100644
--- a/phpBB/includes/message_parser.php
+++ b/phpBB/includes/message_parser.php
@@ -115,10 +115,10 @@ class bbcode_firstpass extends bbcode
'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#ise' => "\$this->bbcode_attachment('\$1', '\$2')")),
'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#ise' => "\$this->bbcode_strong('\$1')")),
'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#ise' => "\$this->bbcode_italic('\$1')")),
- 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")),
+ 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\]((?s).*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")),
'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#iUe' => "\$this->bbcode_img('\$1')")),
'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")),
- 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")),
+ 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")),
'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#ise' => "\$this->bbcode_underline('\$1')")),
'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#ise' => "\$this->bbcode_parse_list('\$0')")),
'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#ise' => "\$this->validate_email('\$1', '\$2')")),
@@ -1062,10 +1062,21 @@ class parse_message extends bbcode_firstpass
{
global $config, $db, $user;
- $mode = ($mode != 'post') ? 'sig' : 'post';
-
$this->mode = $mode;
+ if (!isset($config['max_' . $mode . '_chars']))
+ {
+ $config['max_' . $mode . '_chars'] = 0;
+ }
+ if (!isset($config['max_' . $mode . '_smilies']))
+ {
+ $config['max_' . $mode . '_smilies'] = 0;
+ }
+ if (!isset($config['max_' . $mode . '_urls']))
+ {
+ $config['max_' . $mode . '_urls'] = 0;
+ }
+
$this->allow_img_bbcode = $allow_img_bbcode;
$this->allow_flash_bbcode = $allow_flash_bbcode;
$this->allow_quote_bbcode = $allow_quote_bbcode;
@@ -1089,14 +1100,22 @@ class parse_message extends bbcode_firstpass
$replace = array("\\1:");
$this->message = preg_replace($match, $replace, trim($this->message));
- // Message length check. 0 disables this check completely.
- if ($config['max_' . $mode . '_chars'] > 0)
- {
- $msg_len = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message));
+ // Store message length...
+ $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message));
- if ((!$msg_len && $mode !== 'sig') || $config['max_' . $mode . '_chars'] && $msg_len > $config['max_' . $mode . '_chars'])
+ // Maximum message length check. 0 disables this check completely.
+ if ((int) $config['max_' . $mode . '_chars'] > 0 && $message_length > (int) $config['max_' . $mode . '_chars'])
+ {
+ $this->warn_msg[] = sprintf($user->lang['TOO_MANY_CHARS_' . strtoupper($mode)], $message_length, (int) $config['max_' . $mode . '_chars']);
+ return (!$update_this_message) ? $return_message : $this->warn_msg;
+ }
+
+ // Minimum message length check for post only
+ if ($mode === 'post')
+ {
+ if (!$message_length || $message_length < (int) $config['min_post_chars'])
{
- $this->warn_msg[] = (!$msg_len) ? $user->lang['TOO_FEW_CHARS'] : sprintf($user->lang['TOO_MANY_CHARS_' . strtoupper($mode)], $msg_len, $config['max_' . $mode . '_chars']);
+ $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : sprintf($user->lang['TOO_FEW_CHARS_LIMIT'], $message_length, (int) $config['min_post_chars']);
return (!$update_this_message) ? $return_message : $this->warn_msg;
}
}
@@ -1145,7 +1164,7 @@ class parse_message extends bbcode_firstpass
// Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length.
// The maximum length check happened before any parsings.
- if ($mode !== 'sig' && utf8_clean_string($this->message) === '')
+ if ($mode === 'post' && utf8_clean_string($this->message) === '')
{
$this->warn_msg[] = $user->lang['TOO_FEW_CHARS'];
return (!$update_this_message) ? $return_message : $this->warn_msg;
@@ -1298,7 +1317,7 @@ class parse_message extends bbcode_firstpass
}
// (assertion)
- $match[] = '(?<=^|[\n .])' . preg_quote($row['code'], '#') . '(?![^<>]*>)';
+ $match[] = preg_quote($row['code'], '#');
$replace[] = '
![' . $row['emotion'] . ' ' . $row['code'] . ']({SMILIES_PATH}/' . $row['smiley_url'] . ')
';
}
$db->sql_freeresult($result);
@@ -1308,7 +1327,7 @@ class parse_message extends bbcode_firstpass
{
if ($max_smilies)
{
- $num_matches = preg_match_all('#' . implode('|', $match) . '#', $this->message, $matches);
+ $num_matches = preg_match_all('#(?<=^|[\n .])(?:' . implode('|', $match) . ')(?![^<>]*>)#', $this->message, $matches);
unset($matches);
if ($num_matches !== false && $num_matches > $max_smilies)
@@ -1319,14 +1338,14 @@ class parse_message extends bbcode_firstpass
}
// Make sure the delimiter # is added in front and at the end of every element within $match
- $this->message = trim(preg_replace(explode(chr(0), '#' . implode('#' . chr(0) . '#', $match) . '#'), $replace, $this->message));
+ $this->message = trim(preg_replace(explode(chr(0), '#(?<=^|[\n .])' . implode('(?![^<>]*>)#' . chr(0) . '#(?<=^|[\n .])', $match) . '(?![^<>]*>)#'), $replace, $this->message));
}
}
/**
* Parse Attachments
*/
- function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
+ function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false, $post_msg_id = 0, $topic_id = 0)
{
global $config, $auth, $user, $phpbb_root_path, $phpEx, $db;
@@ -1479,16 +1498,25 @@ class parse_message extends bbcode_firstpass
'filesize' => $filedata['filesize'],
'filetime' => $filedata['filetime'],
'thumbnail' => $filedata['thumbnail'],
- 'is_orphan' => 1,
+ 'is_orphan' => ($post_msg_id) ? 0 : 1,
'in_message' => ($is_message) ? 1 : 0,
'poster_id' => $user->data['user_id'],
);
+ if ($post_msg_id)
+ {
+ $sql_ary['post_msg_id'] = $post_msg_id;
+ if ($topic_id)
+ {
+ $sql_ary['topic_id'] = $topic_id;
+ }
+ }
+
$db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
$new_entry = array(
'attach_id' => $db->sql_nextid(),
- 'is_orphan' => 1,
+ 'is_orphan' => ($post_msg_id) ? 0 : 1,
'real_filename' => $filedata['real_filename'],
'attach_comment'=> $this->filename_data['filecomment'],
);
@@ -1612,7 +1640,7 @@ class parse_message extends bbcode_firstpass
$this->message = $poll['poll_option_text'];
$bbcode_bitfield = $this->bbcode_bitfield;
- $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
+ $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll');
$bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield));
$this->message = $tmp_message;
@@ -1635,7 +1663,7 @@ class parse_message extends bbcode_firstpass
{
$this->warn_msg[] = $user->lang['POLL_TITLE_TOO_LONG'];
}
- $poll['poll_title'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
+ $poll['poll_title'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll');
if (strlen($poll['poll_title']) > 255)
{
$this->warn_msg[] = $user->lang['POLL_TITLE_COMP_TOO_LONG'];
diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php
new file mode 100644
index 0000000000..1d015576a7
--- /dev/null
+++ b/phpBB/includes/questionnaire/questionnaire.php
@@ -0,0 +1,471 @@
+
+* @copyright (c) 2007-2008 Johannes Schlueter
+*/
+class phpbb_questionnaire_data_collector
+{
+ var $providers;
+ var $data = null;
+ var $install_id = '';
+
+ /**
+ * Constructor.
+ *
+ * @param string
+ */
+ function phpbb_questionnaire_data_collector($install_id)
+ {
+ $this->install_id = $install_id;
+ $this->providers = array();
+ }
+
+ function add_data_provider(&$provider)
+ {
+ $this->providers[] = &$provider;
+ }
+
+ /**
+ * Get data as an array.
+ *
+ * @return array All Data
+ */
+ function get_data_raw()
+ {
+ if (!$this->data)
+ {
+ $this->collect();
+ }
+
+ return $this->data;
+ }
+
+ function get_data_for_form()
+ {
+ return base64_encode(serialize($this->get_data_raw()));
+ }
+
+ /**
+ * Collect info into the data property.
+ *
+ * @return void
+ */
+ function collect()
+ {
+ foreach (array_keys($this->providers) as $key)
+ {
+ $provider = &$this->providers[$key];
+ $this->data[$provider->get_identifier()] = $provider->get_data();
+ }
+ $this->data['install_id'] = $this->install_id;
+ }
+}
+
+/** interface: get_indentifier(), get_data() */
+
+/**
+* Questionnaire PHP data provider
+* @package phpBB3
+*/
+class phpbb_questionnaire_php_data_provider
+{
+ function get_identifier()
+ {
+ return 'PHP';
+ }
+
+ /**
+ * Get data about the PHP runtime setup.
+ *
+ * @return array
+ */
+ function get_data()
+ {
+ return array(
+ 'version' => PHP_VERSION,
+ 'sapi' => PHP_SAPI,
+ 'int_size' => defined('PHP_INT_SIZE') ? PHP_INT_SIZE : '',
+ 'safe_mode' => (int) @ini_get('safe_mode'),
+ 'open_basedir' => (int) @ini_get('open_basedir'),
+ 'memory_limit' => @ini_get('memory_limit'),
+ 'allow_url_fopen' => (int) @ini_get('allow_url_fopen'),
+ 'allow_url_include' => (int) @ini_get('allow_url_include'),
+ 'file_uploads' => (int) @ini_get('file_uploads'),
+ 'upload_max_filesize' => @ini_get('upload_max_filesize'),
+ 'post_max_size' => @ini_get('post_max_size'),
+ 'disable_functions' => @ini_get('disable_functions'),
+ 'disable_classes' => @ini_get('disable_classes'),
+ 'enable_dl' => (int) @ini_get('enable_dl'),
+ 'magic_quotes_gpc' => (int) @ini_get('magic_quotes_gpc'),
+ 'register_globals' => (int) @ini_get('register_globals'),
+ 'filter.default' => @ini_get('filter.default'),
+ 'zend.ze1_compatibility_mode' => (int) @ini_get('zend.ze1_compatibility_mode'),
+ 'unicode.semantics' => (int) @ini_get('unicode.semantics'),
+ 'zend_thread_safty' => (int) function_exists('zend_thread_id'),
+ 'extensions' => get_loaded_extensions(),
+ );
+ }
+}
+
+/**
+* Questionnaire System data provider
+* @package phpBB3
+*/
+class phpbb_questionnaire_system_data_provider
+{
+ function get_identifier()
+ {
+ return 'System';
+ }
+
+ /**
+ * Get data about the general system information, like OS or IP (shortened).
+ *
+ * @return array
+ */
+ function get_data()
+ {
+ // Start discovering the IPV4 server address, if available
+ $server_address = '0.0.0.0';
+
+ if (!empty($_SERVER['SERVER_ADDR']))
+ {
+ $server_address = $_SERVER['SERVER_ADDR'];
+ }
+
+ // Running on IIS?
+ if (!empty($_SERVER['LOCAL_ADDR']))
+ {
+ $server_address = $_SERVER['LOCAL_ADDR'];
+ }
+
+ $ip_address_ary = explode('.', $server_address);
+
+ // build ip
+ if (!isset($ip_address_ary[0]) || !isset($ip_address_ary[1]))
+ {
+ $ip_address_ary = explode('.', '0.0.0.0');
+ }
+
+ return array(
+ 'os' => PHP_OS,
+ 'httpd' => $_SERVER['SERVER_SOFTWARE'],
+ // we don't want the real IP address (for privacy policy reasons) but only
+ // a network address to see whether your installation is running on a private or public network.
+ // IANA reserved addresses for private networks (RFC 1918) are:
+ // - 10.0.0.0/8
+ // - 172.16.0.0/12
+ // - 192.168.0.0/16
+ 'ip' => $ip_address_ary[0] . '.' . $ip_address_ary[1] . '.XXX.YYY',
+ );
+ }
+}
+
+/**
+* Questionnaire phpBB data provider
+* @package phpBB3
+*/
+class phpbb_questionnaire_phpbb_data_provider
+{
+ var $config;
+ var $unique_id;
+
+ /**
+ * Constructor.
+ *
+ * @param array $config
+ */
+ function phpbb_questionnaire_phpbb_data_provider($config)
+ {
+ // generate a unique id if necessary
+ if (empty($config['questionnaire_unique_id']))
+ {
+ $this->unique_id = unique_id();
+ set_config('questionnaire_unique_id', $this->unique_id);
+ }
+ else
+ {
+ $this->unique_id = $config['questionnaire_unique_id'];
+ }
+
+ $this->config = $config;
+ }
+
+ /**
+ * Returns a string identifier for this data provider
+ *
+ * @return string "phpBB"
+ */
+ function get_identifier()
+ {
+ return 'phpBB';
+ }
+
+ /**
+ * Get data about this phpBB installation.
+ *
+ * @return array Relevant anonymous config options
+ */
+ function get_data()
+ {
+ global $phpbb_root_path, $phpEx;
+ include("{$phpbb_root_path}config.$phpEx");
+
+ // Only send certain config vars
+ $config_vars = array(
+ 'active_sessions' => true,
+ 'allow_attachments' => true,
+ 'allow_autologin' => true,
+ 'allow_avatar' => true,
+ 'allow_avatar_local' => true,
+ 'allow_avatar_remote' => true,
+ 'allow_avatar_upload' => true,
+ 'allow_bbcode' => true,
+ 'allow_birthdays' => true,
+ 'allow_bookmarks' => true,
+ 'allow_emailreuse' => true,
+ 'allow_forum_notify' => true,
+ 'allow_mass_pm' => true,
+ 'allow_name_chars' => true,
+ 'allow_namechange' => true,
+ 'allow_nocensors' => true,
+ 'allow_pm_attach' => true,
+ 'allow_pm_report' => true,
+ 'allow_post_flash' => true,
+ 'allow_post_links' => true,
+ 'allow_privmsg' => true,
+ 'allow_quick_reply' => true,
+ 'allow_sig' => true,
+ 'allow_sig_bbcode' => true,
+ 'allow_sig_flash' => true,
+ 'allow_sig_img' => true,
+ 'allow_sig_links' => true,
+ 'allow_sig_pm' => true,
+ 'allow_sig_smilies' => true,
+ 'allow_smilies' => true,
+ 'allow_topic_notify' => true,
+ 'attachment_quota' => true,
+ 'auth_bbcode_pm' => true,
+ 'auth_flash_pm' => true,
+ 'auth_img_pm' => true,
+ 'auth_method' => true,
+ 'auth_smilies_pm' => true,
+ 'avatar_filesize' => true,
+ 'avatar_max_height' => true,
+ 'avatar_max_width' => true,
+ 'avatar_min_height' => true,
+ 'avatar_min_width' => true,
+ 'board_dst' => true,
+ 'board_email_form' => true,
+ 'board_hide_emails' => true,
+ 'board_timezone' => true,
+ 'browser_check' => true,
+ 'bump_interval' => true,
+ 'bump_type' => true,
+ 'cache_gc' => true,
+ 'captcha_plugin' => true,
+ 'captcha_gd' => true,
+ 'captcha_gd_foreground_noise' => true,
+ 'captcha_gd_x_grid' => true,
+ 'captcha_gd_y_grid' => true,
+ 'captcha_gd_wave' => true,
+ 'captcha_gd_3d_noise' => true,
+ 'captcha_gd_fonts' => true,
+ 'confirm_refresh' => true,
+ 'check_attachment_content' => true,
+ 'check_dnsbl' => true,
+ 'chg_passforce' => true,
+ 'cookie_secure' => true,
+ 'coppa_enable' => true,
+ 'database_gc' => true,
+ 'dbms_version' => true,
+ 'default_dateformat' => true,
+ 'display_last_edited' => true,
+ 'display_order' => true,
+ 'edit_time' => true,
+ 'email_check_mx' => true,
+ 'email_enable' => true,
+ 'email_function_name' => true,
+ 'email_package_size' => true,
+ 'enable_confirm' => true,
+ 'enable_pm_icons' => true,
+ 'enable_post_confirm' => true,
+ 'feed_enable' => true,
+ 'feed_limit' => true,
+ 'feed_overall_forums' => true,
+ 'feed_overall_forums_limit' => true,
+ 'feed_overall_topics' => true,
+ 'feed_overall_topics_limit' => true,
+ 'feed_forum' => true,
+ 'feed_topic' => true,
+ 'feed_item_statistics' => true,
+ 'flood_interval' => true,
+ 'force_server_vars' => true,
+ 'form_token_lifetime' => true,
+ 'form_token_mintime' => true,
+ 'form_token_sid_guests' => true,
+ 'forward_pm' => true,
+ 'forwarded_for_check' => true,
+ 'full_folder_action' => true,
+ 'fulltext_native_common_thres' => true,
+ 'fulltext_native_load_upd' => true,
+ 'fulltext_native_max_chars' => true,
+ 'fulltext_native_min_chars' => true,
+ 'gzip_compress' => true,
+ 'hot_threshold' => true,
+ 'img_create_thumbnail' => true,
+ 'img_display_inlined' => true,
+ 'img_imagick' => true,
+ 'img_link_height' => true,
+ 'img_link_width' => true,
+ 'img_max_height' => true,
+ 'img_max_thumb_width' => true,
+ 'img_max_width' => true,
+ 'img_min_thumb_filesize' => true,
+ 'ip_check' => true,
+ 'jab_enable' => true,
+ 'jab_package_size' => true,
+ 'jab_use_ssl' => true,
+ 'limit_load' => true,
+ 'limit_search_load' => true,
+ 'load_anon_lastread' => true,
+ 'load_birthdays' => true,
+ 'load_cpf_memberlist' => true,
+ 'load_cpf_viewprofile' => true,
+ 'load_cpf_viewtopic' => true,
+ 'load_db_lastread' => true,
+ 'load_db_track' => true,
+ 'load_jumpbox' => true,
+ 'load_moderators' => true,
+ 'load_online' => true,
+ 'load_online_guests' => true,
+ 'load_online_time' => true,
+ 'load_onlinetrack' => true,
+ 'load_search' => true,
+ 'load_tplcompile' => true,
+ 'load_user_activity' => true,
+ 'max_attachments' => true,
+ 'max_attachments_pm' => true,
+ 'max_autologin_time' => true,
+ 'max_filesize' => true,
+ 'max_filesize_pm' => true,
+ 'max_login_attempts' => true,
+ 'max_name_chars' => true,
+ 'max_num_search_keywords' => true,
+ 'max_pass_chars' => true,
+ 'max_poll_options' => true,
+ 'max_post_chars' => true,
+ 'max_post_font_size' => true,
+ 'max_post_img_height' => true,
+ 'max_post_img_width' => true,
+ 'max_post_smilies' => true,
+ 'max_post_urls' => true,
+ 'max_quote_depth' => true,
+ 'max_reg_attempts' => true,
+ 'max_sig_chars' => true,
+ 'max_sig_font_size' => true,
+ 'max_sig_img_height' => true,
+ 'max_sig_img_width' => true,
+ 'max_sig_smilies' => true,
+ 'max_sig_urls' => true,
+ 'min_name_chars' => true,
+ 'min_pass_chars' => true,
+ 'min_post_chars' => true,
+ 'min_search_author_chars' => true,
+ 'mime_triggers' => true,
+ 'new_member_post_limit' => true,
+ 'new_member_group_default' => true,
+ 'override_user_style' => true,
+ 'pass_complex' => true,
+ 'pm_edit_time' => true,
+ 'pm_max_boxes' => true,
+ 'pm_max_msgs' => true,
+ 'pm_max_recipients' => true,
+ 'posts_per_page' => true,
+ 'print_pm' => true,
+ 'queue_interval' => true,
+ 'require_activation' => true,
+ 'referer_validation' => true,
+ 'search_block_size' => true,
+ 'search_gc' => true,
+ 'search_interval' => true,
+ 'search_anonymous_interval' => true,
+ 'search_type' => true,
+ 'search_store_results' => true,
+ 'secure_allow_deny' => true,
+ 'secure_allow_empty_referer' => true,
+ 'secure_downloads' => true,
+ 'session_gc' => true,
+ 'session_length' => true,
+ 'smtp_auth_method' => true,
+ 'smtp_delivery' => true,
+ 'topics_per_page' => true,
+ 'tpl_allow_php' => true,
+ 'version' => true,
+ 'warnings_expire_days' => true,
+ 'warnings_gc' => true,
+
+ 'num_files' => true,
+ 'num_posts' => true,
+ 'num_topics' => true,
+ 'num_users' => true,
+ 'record_online_users' => true,
+ );
+
+ $result = array();
+ foreach ($config_vars as $name => $void)
+ {
+ if (isset($this->config[$name]))
+ {
+ $result['config_' . $name] = $this->config[$name];
+ }
+ }
+
+ $result['dbms'] = $dbms;
+ $result['acm_type'] = $acm_type;
+ $result['load_extensions'] = $load_extensions;
+ $result['user_agent'] = 'Unknown';
+
+ // Try to get user agent vendor and version
+ $match = array();
+ $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
+ $agents = array('firefox', 'msie', 'opera', 'chrome', 'safari', 'mozilla', 'seamonkey', 'konqueror', 'netscape', 'gecko', 'navigator', 'mosaic', 'lynx', 'amaya', 'omniweb', 'avant', 'camino', 'flock', 'aol');
+
+ // We check here 1 by 1 because some strings occur after others (for example Mozilla [...] Firefox/)
+ foreach ($agents as $agent)
+ {
+ if (preg_match('#(' . $agent . ')[/ ]?([0-9.]*)#i', $user_agent, $match))
+ {
+ $result['user_agent'] = $match[1] . ' ' . $match[2];
+ break;
+ }
+ }
+
+ return $result;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index e1e7951367..d1c1ff00d1 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -324,16 +324,17 @@ class fulltext_mysql extends search_backend
* Performs a search on keywords depending on display specific params. You have to run split_keywords() first.
*
* @param string $type contains either posts or topics depending on what should be searched for
- * @param string &$fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
- * @param string &$terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
- * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query
- * @param string &$sort_key is the key of $sort_by_sql for the selected sorting
- * @param string &$sort_dir is either a or d representing ASC and DESC
- * @param string &$sort_days specifies the maximum amount of days a post may be old
- * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched
- * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
- * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
- * @param array &$author_ary an array of author ids if the author should be ignored during the search the array is empty
+ * @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
+ * @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
+ * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
+ * @param string $sort_key is the key of $sort_by_sql for the selected sorting
+ * @param string $sort_dir is either a or d representing ASC and DESC
+ * @param string $sort_days specifies the maximum amount of days a post may be old
+ * @param array $ex_fid_ary specifies an array of forum ids which should not be searched
+ * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
+ * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
+ * @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
+ * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
@@ -341,7 +342,7 @@ class fulltext_mysql extends search_backend
*
* @access public
*/
- function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
+ function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
@@ -440,14 +441,26 @@ class fulltext_mysql extends search_backend
$sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';
$sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : '';
$field = ($type == 'posts') ? 'post_id' : 'topic_id';
- $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')';
+ if (sizeof($author_ary) && $author_name)
+ {
+ // first one matches post of registered users, second one guests and deleted users
+ $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
+ }
+ else if (sizeof($author_ary))
+ {
+ $sql_author = ' AND ' . $db->sql_in_set('p.poster_id', $author_ary);
+ }
+ else
+ {
+ $sql_author = '';
+ }
$sql_where_options = $sql_sort_join;
$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';
$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= $m_approve_fid_sql;
- $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : '';
+ $sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_where_options .= $sql_match_where;
@@ -495,12 +508,25 @@ class fulltext_mysql extends search_backend
/**
* Performs a search on an author's posts without caring about message contents. Depends on display specific params
*
- * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
- * @param int $start indicates the first index of the page
- * @param int $per_page number of ids each page is supposed to contain
- * @return total number of results
+ * @param string $type contains either posts or topics depending on what should be searched for
+ * @param boolean $firstpost_only if true, only topic starting posts will be considered
+ * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
+ * @param string $sort_key is the key of $sort_by_sql for the selected sorting
+ * @param string $sort_dir is either a or d representing ASC and DESC
+ * @param string $sort_days specifies the maximum amount of days a post may be old
+ * @param array $ex_fid_ary specifies an array of forum ids which should not be searched
+ * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
+ * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
+ * @param array $author_ary an array of author ids
+ * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
+ * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
+ * @param int $start indicates the first index of the page
+ * @param int $per_page number of ids each page is supposed to contain
+ * @return boolean|int total number of results
+ *
+ * @access public
*/
- function author_search($type, $firstpost_only, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
+ function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
@@ -522,7 +548,8 @@ class fulltext_mysql extends search_backend
$topic_id,
implode(',', $ex_fid_ary),
implode(',', $m_approve_fid_ary),
- implode(',', $author_ary)
+ implode(',', $author_ary),
+ $author_name,
)));
// try reading the results from cache
@@ -535,7 +562,15 @@ class fulltext_mysql extends search_backend
$id_ary = array();
// Create some display specific sql strings
- $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
+ if ($author_name)
+ {
+ // first one matches post of registered users, second one guests and deleted users
+ $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
+ }
+ else
+ {
+ $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
+ }
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php
index 8df5ddfbae..5af3929ccd 100644
--- a/phpBB/includes/search/fulltext_native.php
+++ b/phpBB/includes/search/fulltext_native.php
@@ -392,16 +392,17 @@ class fulltext_native extends search_backend
* Performs a search on keywords depending on display specific params. You have to run split_keywords() first.
*
* @param string $type contains either posts or topics depending on what should be searched for
- * @param string &$fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
- * @param string &$terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
- * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query
- * @param string &$sort_key is the key of $sort_by_sql for the selected sorting
- * @param string &$sort_dir is either a or d representing ASC and DESC
- * @param string &$sort_days specifies the maximum amount of days a post may be old
- * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched
- * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
- * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
- * @param array &$author_ary an array of author ids if the author should be ignored during the search the array is empty
+ * @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
+ * @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
+ * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
+ * @param string $sort_key is the key of $sort_by_sql for the selected sorting
+ * @param string $sort_dir is either a or d representing ASC and DESC
+ * @param string $sort_days specifies the maximum amount of days a post may be old
+ * @param array $ex_fid_ary specifies an array of forum ids which should not be searched
+ * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
+ * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
+ * @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
+ * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
@@ -409,7 +410,7 @@ class fulltext_native extends search_backend
*
* @access public
*/
- function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
+ function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
@@ -432,7 +433,8 @@ class fulltext_native extends search_backend
$topic_id,
implode(',', $ex_fid_ary),
implode(',', $m_approve_fid_ary),
- implode(',', $author_ary)
+ implode(',', $author_ary),
+ $author_name,
)));
// try reading the results from cache
@@ -623,7 +625,16 @@ class fulltext_native extends search_backend
if (sizeof($author_ary))
{
- $sql_where[] = $db->sql_in_set('p.poster_id', $author_ary);
+ if ($author_name)
+ {
+ // first one matches post of registered users, second one guests and deleted users
+ $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
+ }
+ else
+ {
+ $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
+ }
+ $sql_where[] = $sql_author;
}
if (sizeof($ex_fid_ary))
@@ -773,14 +784,15 @@ class fulltext_native extends search_backend
*
* @param string $type contains either posts or topics depending on what should be searched for
* @param boolean $firstpost_only if true, only topic starting posts will be considered
- * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query
- * @param string &$sort_key is the key of $sort_by_sql for the selected sorting
- * @param string &$sort_dir is either a or d representing ASC and DESC
- * @param string &$sort_days specifies the maximum amount of days a post may be old
- * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched
- * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
- * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
- * @param array &$author_ary an array of author ids
+ * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
+ * @param string $sort_key is the key of $sort_by_sql for the selected sorting
+ * @param string $sort_dir is either a or d representing ASC and DESC
+ * @param string $sort_days specifies the maximum amount of days a post may be old
+ * @param array $ex_fid_ary specifies an array of forum ids which should not be searched
+ * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
+ * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
+ * @param array $author_ary an array of author ids
+ * @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
@@ -788,7 +800,7 @@ class fulltext_native extends search_backend
*
* @access public
*/
- function author_search($type, $firstpost_only, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
+ function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
@@ -810,7 +822,8 @@ class fulltext_native extends search_backend
$topic_id,
implode(',', $ex_fid_ary),
implode(',', $m_approve_fid_ary),
- implode(',', $author_ary)
+ implode(',', $author_ary),
+ $author_name,
)));
// try reading the results from cache
@@ -823,7 +836,15 @@ class fulltext_native extends search_backend
$id_ary = array();
// Create some display specific sql strings
- $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
+ if ($author_name)
+ {
+ // first one matches post of registered users, second one guests and deleted users
+ $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
+ }
+ else
+ {
+ $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
+ }
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 043a637584..dcfde14159 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -213,7 +213,7 @@ class session
$this->update_session_page = $update_session_page;
$this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';
$this->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : '';
- $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
+ $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? htmlspecialchars((string) $_SERVER['HTTP_X_FORWARDED_FOR']) : '';
$this->host = $this->extract_current_hostname();
$this->page = $this->extract_current_page($phpbb_root_path);
@@ -221,10 +221,10 @@ class session
// if the forwarded for header shall be checked we have to validate its contents
if ($config['forwarded_for_check'])
{
- $this->forwarded_for = preg_replace('#, +#', ', ', $this->forwarded_for);
+ $this->forwarded_for = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->forwarded_for));
// split the list of IPs
- $ips = explode(', ', $this->forwarded_for);
+ $ips = explode(' ', $this->forwarded_for);
foreach ($ips as $ip)
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
@@ -267,7 +267,28 @@ class session
// Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
// it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
- $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
+ $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars((string) $_SERVER['REMOTE_ADDR']) : '';
+ $this->ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->ip));
+
+ // split the list of IPs
+ $ips = explode(' ', $this->ip);
+
+ // Default IP if REMOTE_ADDR is invalid
+ $this->ip = '127.0.0.1';
+
+ foreach ($ips as $ip)
+ {
+ // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
+ if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
+ {
+ // Just break
+ break;
+ }
+
+ // Use the last in chain
+ $this->ip = $ip;
+ }
+
$this->load = false;
// Load limit check (if applicable)
@@ -396,6 +417,11 @@ class session
WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
$db->sql_query($sql);
}
+
+ if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts'])
+ {
+ $this->leave_newly_registered();
+ }
}
$this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
@@ -601,7 +627,7 @@ class session
}
else
{
- $ips = explode(', ', $this->forwarded_for);
+ $ips = explode(' ', $this->forwarded_for);
$ips[] = $this->ip;
$this->check_ban($this->data['user_id'], $ips);
}
@@ -891,7 +917,7 @@ class session
*/
function session_gc()
{
- global $db, $config;
+ global $db, $config, $phpbb_root_path, $phpEx;
$batch_size = 10;
@@ -949,43 +975,18 @@ class session
WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time']));
$db->sql_query($sql);
}
- $this->confirm_gc();
+
+ // only called from CRON; should be a safe workaround until the infrastructure gets going
+ if (!class_exists('captcha_factory'))
+ {
+ include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx);
+ }
+ phpbb_captcha_factory::garbage_collect($config['captcha_plugin']);
}
return;
}
- function confirm_gc($type = 0)
- {
- global $db, $config;
-
- $sql = 'SELECT DISTINCT c.session_id
- FROM ' . CONFIRM_TABLE . ' c
- LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id)
- WHERE s.session_id IS NULL' .
- ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type);
- $result = $db->sql_query($sql);
-
- if ($row = $db->sql_fetchrow($result))
- {
- $sql_in = array();
- do
- {
- $sql_in[] = (string) $row['session_id'];
- }
- while ($row = $db->sql_fetchrow($result));
-
- if (sizeof($sql_in))
- {
- $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
- WHERE ' . $db->sql_in_set('session_id', $sql_in);
- $db->sql_query($sql);
- }
- }
- $db->sql_freeresult($result);
- }
-
-
/**
* Sets a cookie
*
@@ -1360,6 +1361,20 @@ class session
WHERE user_id = ' . (int) $user_id;
$db->sql_query($sql);
+ // Update last visit info first before deleting sessions
+ $sql = 'SELECT session_time, session_page
+ FROM ' . SESSIONS_TABLE . '
+ WHERE session_user_id = ' . (int) $user_id . '
+ ORDER BY session_time DESC';
+ $result = $db->sql_query_limit($sql, 1);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_lastvisit = ' . (int) $row['session_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
+ WHERE user_id = " . (int) $user_id;
+ $db->sql_query($sql);
+
// Let's also clear any current sessions for the specified user_id
// If it's the current user then we'll leave this session intact
$sql_where = 'session_user_id = ' . (int) $user_id;
@@ -1384,6 +1399,8 @@ class session
*/
function validate_referer($check_script_path = false)
{
+ global $config;
+
// no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason)
if (empty($this->referer) || empty($this->host))
{
@@ -1393,7 +1410,7 @@ class session
$host = htmlspecialchars($this->host);
$ref = substr($this->referer, strpos($this->referer, '://') + 3);
- if (!(stripos($ref, $host) === 0) && (!$config['force_server'] || !(stripos($ref, $config['server_name']) === 0)))
+ if (!(stripos($ref, $host) === 0) && (!$config['force_server_vars'] || !(stripos($ref, $config['server_name']) === 0)))
{
return false;
}
@@ -1451,8 +1468,8 @@ class user extends session
var $img_lang;
var $img_array = array();
- // Able to add new option (id 7)
- var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10);
+ // Able to add new options (up to id 31)
+ var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17);
var $keyvalues = array();
/**
@@ -1554,7 +1571,7 @@ class user extends session
$this->add_lang($lang_set);
unset($lang_set);
- if (!empty($_GET['style']) && $auth->acl_get('a_styles'))
+ if (!empty($_GET['style']) && $auth->acl_get('a_styles') && !defined('ADMIN_START'))
{
global $SID, $_EXTRA_URL;
@@ -1776,7 +1793,7 @@ class user extends session
// Disable board if the install/ directory is still present
// For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
- if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install'))
+ if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
{
// Adjust the message slightly according to the permissions
if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))
@@ -1853,7 +1870,7 @@ class user extends session
// Does the user need to change their password? If so, redirect to the
// ucp profile reg_details page ... of course do not redirect if we're already in the ucp
- if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && $this->data['is_registered'] && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
+ if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
{
if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
{
@@ -2026,6 +2043,34 @@ class user extends session
$language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx;
}
+ if (!file_exists($language_filename))
+ {
+ global $config;
+
+ if ($this->lang_name == 'en')
+ {
+ // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en.
+ $language_filename = str_replace($this->lang_path . 'en', $this->lang_path . $this->data['user_lang'], $language_filename);
+ trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
+ }
+ else if ($this->lang_name == basename($config['default_lang']))
+ {
+ // Fall back to the English Language
+ $this->lang_name = 'en';
+ $this->set_lang($lang, $help, $lang_file, $use_db, $use_help);
+ }
+ else if ($this->lang_name == $this->data['user_lang'])
+ {
+ // Fall back to the board default language
+ $this->lang_name = basename($config['default_lang']);
+ $this->set_lang($lang, $help, $lang_file, $use_db, $use_help);
+ }
+
+ // Reset the lang name
+ $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
+ return;
+ }
+
// Do not suppress error if in DEBUG_EXTRA mode
$include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename);
@@ -2186,7 +2231,10 @@ class user extends session
return $img_data;
}
- $img_data['src'] = $phpbb_root_path . 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename'];
+ // Use URL if told so
+ $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
+
+ $img_data['src'] = $root_path . 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename'];
$img_data['width'] = $this->img_array[$img]['image_width'];
$img_data['height'] = $this->img_array[$img]['image_height'];
}
@@ -2259,6 +2307,36 @@ class user extends session
return $var;
}
}
+
+ /**
+ * Funtion to make the user leave the NEWLY_REGISTERED system group.
+ * @access public
+ */
+ function leave_newly_registered()
+ {
+ global $db;
+
+ if (empty($this->data['user_new']))
+ {
+ return false;
+ }
+
+ if (!function_exists('remove_newly_registered'))
+ {
+ global $phpbb_root_path, $phpEx;
+
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ }
+ if ($group = remove_newly_registered($this->data['user_id'], $this->data))
+ {
+ $this->data['group_id'] = $group;
+
+ }
+ $this->data['user_permissions'] = '';
+ $this->data['user_new'] = 0;
+
+ return true;
+ }
}
?>
\ No newline at end of file
diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php
index 0098c484bd..80434aca4c 100644
--- a/phpBB/includes/template.php
+++ b/phpBB/includes/template.php
@@ -39,6 +39,8 @@ class template
var $files_inherit = array();
var $files_template = array();
var $inherit_root = '';
+ var $orig_tpl_storedb;
+ var $orig_tpl_inherits_id;
// this will hash handle names to the compiled/uncompiled code for that handle.
var $compiled_code = array();
@@ -55,7 +57,20 @@ class template
{
$this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template';
$this->cachepath = $phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $user->theme['template_path']) . '_';
-
+
+ if ($this->orig_tpl_storedb === null)
+ {
+ $this->orig_tpl_storedb = $user->theme['template_storedb'];
+ }
+
+ if ($this->orig_tpl_inherits_id === null)
+ {
+ $this->orig_tpl_inherits_id = $user->theme['template_inherits_id'];
+ }
+
+ $user->theme['template_storedb'] = $this->orig_tpl_storedb;
+ $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id;
+
if ($user->theme['template_inherits_id'])
{
$this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template';
@@ -77,10 +92,20 @@ class template
*/
function set_custom_template($template_path, $template_name)
{
- global $phpbb_root_path;
+ global $phpbb_root_path, $user;
+
+ // Make sure $template_path has no ending slash
+ if (substr($template_path, -1) == '/')
+ {
+ $template_path = substr($template_path, 0, -1);
+ }
$this->root = $template_path;
$this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_';
+ $user->theme['template_storedb'] = false;
+ $user->theme['template_inherits_id'] = false;
+
+ $this->_rootref = &$this->_tpldata['.'][0];
return true;
}
@@ -105,13 +130,13 @@ class template
$this->filename[$handle] = $filename;
$this->files[$handle] = $this->root . '/' . $filename;
-
+
if ($this->inherit_root)
{
$this->files_inherit[$handle] = $this->inherit_root . '/' . $filename;
}
}
-
+
return true;
}
@@ -209,7 +234,7 @@ class template
return true;
}
-
+
/**
* Load a compiled template if possible, if not, recompile it
* @access private
@@ -220,7 +245,7 @@ class template
$filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx;
$this->files_template[$handle] = $user->theme['template_id'];
-
+
$recompile = false;
if (!file_exists($filename) || @filesize($filename) === 0)
{
@@ -236,7 +261,7 @@ class template
}
$recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false;
}
-
+
// Recompile page if the original template is newer, otherwise load the compiled version
if (!$recompile)
{
@@ -249,14 +274,14 @@ class template
{
include($phpbb_root_path . 'includes/functions_template.' . $phpEx);
}
-
+
// Inheritance - we point to another template file for this one. Equality is also used for store_db
if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle]))
{
$this->files[$handle] = $this->files_inherit[$handle];
$this->files_template[$handle] = $user->theme['template_inherits_id'];
}
-
+
$compile = new template_compile($this);
// If we don't have a file assigned to this handle, die.
@@ -282,7 +307,7 @@ class template
$ids[] = $user->theme['template_inherits_id'];
}
$ids[] = $user->theme['template_id'];
-
+
foreach ($ids as $id)
{
$sql = 'SELECT *
@@ -290,7 +315,7 @@ class template
WHERE template_id = ' . $id . "
AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "'
OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')';
-
+
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
@@ -298,7 +323,7 @@ class template
}
$db->sql_freeresult($result);
}
-
+
if (sizeof($rows))
{
foreach ($rows as $row)
@@ -326,7 +351,7 @@ class template
{
$this->files_template[$row['template_filename']] = $user->theme['template_id'];
}
-
+
if ($force_reload || $row['template_mtime'] < filemtime($file))
{
if ($row['template_filename'] == $this->filename[$handle])
@@ -468,7 +493,7 @@ class template
{
unset($this->_tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']);
}
-
+
// Add a new iteration to this block with the variable assignments we were given.
$this->_tpldata[$blockname][] = $vararray;
}
@@ -511,7 +536,7 @@ class template
// Nested blocks are not supported
return false;
}
-
+
// Change key to zero (change first position) if false and to last position if true
if ($key === false || $key === true)
{
@@ -614,6 +639,25 @@ class template
eval(' ?>' . $this->compiled_code[$handle] . '_php_include(): File ' . htmlspecialchars($file) . ' does not exist or is empty';
+ return;
+ }
+ include($file);
+ }
}
?>
\ No newline at end of file
diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php
index b91c88b7e8..445f7c7d2a 100644
--- a/phpBB/includes/ucp/ucp_confirm.php
+++ b/phpBB/includes/ucp/ucp_confirm.php
@@ -3,7 +3,7 @@
*
* @package VC
* @version $Id$
-* @copyright (c) 2005 phpBB Group
+* @copyright (c) 2005 2008 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
@@ -37,42 +37,10 @@ class ucp_confirm
{
global $db, $user, $phpbb_root_path, $config, $phpEx;
- // Do we have an id? No, then just exit
- $confirm_id = request_var('id', '');
- $type = request_var('type', 0);
-
- if (!$confirm_id || !$type)
- {
- exit;
- }
-
- // Try and grab code for this id and session
- $sql = 'SELECT code, seed
- FROM ' . CONFIRM_TABLE . "
- WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND confirm_type = $type";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // If we have a row then grab data else create a new id
- if (!$row)
- {
- exit;
- }
-
- if ($config['captcha_gd'])
- {
- include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
- }
- else
- {
- include($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx);
- }
-
- $captcha = new captcha();
- $captcha->execute($row['code'], $row['seed']);
+ include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
+ $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $captcha->init(request_var('type', 0));
+ $captcha->execute();
garbage_collection();
exit_handler();
diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php
index 4e40f0a2a3..ea57246527 100644
--- a/phpBB/includes/ucp/ucp_groups.php
+++ b/phpBB/includes/ucp/ucp_groups.php
@@ -41,7 +41,7 @@ class ucp_groups
switch ($mode)
{
case 'membership':
-
+
$this->page_title = 'UCP_USERGROUPS_MEMBER';
if ($submit || isset($_POST['change_default']))
@@ -414,7 +414,7 @@ class ucp_groups
$this->page_title = 'UCP_USERGROUPS_MANAGE';
$action = (isset($_POST['addusers'])) ? 'addusers' : request_var('action', '');
$group_id = request_var('g', 0);
-
+
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
add_form_key('ucp_groups');
@@ -438,10 +438,10 @@ class ucp_groups
{
trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . $return_page, E_USER_WARNING);
}
-
+
$group_name = $group_row['group_name'];
$group_type = $group_row['group_type'];
-
+
$avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '

';
$template->assign_vars(array(
@@ -450,7 +450,7 @@ class ucp_groups
'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '',
'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']),
'GROUP_TYPE' => $group_row['group_type'],
-
+
'AVATAR' => $avatar_img,
'AVATAR_IMAGE' => $avatar_img,
'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '',
@@ -604,13 +604,26 @@ class ucp_groups
// Only set the rank, colour, etc. if it's changed or if we're adding a new
// group. This prevents existing group members being updated if no changes
// were made.
-
+
$group_attributes = array();
- $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients');
- foreach ($test_variables as $test)
+ $test_variables = array(
+ 'rank' => 'int',
+ 'colour' => 'string',
+ 'avatar' => 'string',
+ 'avatar_type' => 'int',
+ 'avatar_width' => 'int',
+ 'avatar_height' => 'int',
+ 'receive_pm' => 'int',
+ 'legend' => 'int',
+ 'message_limit' => 'int',
+ 'max_recipients'=> 'int',
+ );
+
+ foreach ($test_variables as $test => $type)
{
- if ($action == 'add' || (isset($submit_ary[$test]) && $group_row['group_' . $test] != $submit_ary[$test]))
+ if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test]))
{
+ settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
}
}
@@ -675,29 +688,33 @@ class ucp_groups
$display_gallery = (isset($_POST['display_gallery'])) ? true : false;
- if ($config['allow_avatar_local'] && $display_gallery)
+ if ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery)
{
avatar_gallery($category, $avatar_select, 4);
}
-
- $avatars_enabled = ($can_upload || ($config['allow_avatar_local'] || $config['allow_avatar_remote'])) ? true : false;
+
+ $avatars_enabled = ($config['allow_avatar'] && (($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) || ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false;
$template->assign_vars(array(
'S_EDIT' => true,
'S_INCLUDE_SWATCH' => true,
- 'S_CAN_UPLOAD' => $can_upload,
- 'S_FORM_ENCTYPE' => ($can_upload) ? ' enctype="multipart/form-data"' : '',
+ 'S_FORM_ENCTYPE' => ($config['allow_avatar'] && $can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) ? ' enctype="multipart/form-data"' : '',
'S_ERROR' => (sizeof($error)) ? true : false,
'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false,
'S_AVATARS_ENABLED' => $avatars_enabled,
- 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false,
+ 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false,
'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false,
+ 'S_UPLOAD_AVATAR_FILE' => ($config['allow_avatar'] && $config['allow_avatar_upload'] && $can_upload) ? true : false,
+ 'S_UPLOAD_AVATAR_URL' => ($config['allow_avatar'] && $config['allow_avatar_remote_upload'] && $can_upload) ? true : false,
+ 'S_LINK_AVATAR' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false,
+ 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local']) ? true : false,
+
'ERROR_MSG' => (sizeof($error)) ? implode('
', $error) : '',
'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '',
'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0,
'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0,
-
+
'GROUP_DESC' => $group_desc_data['text'],
'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'],
'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'],
@@ -839,6 +856,7 @@ class ucp_groups
'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start),
'U_ACTION' => $this->u_action . "&g=$group_id",
+ 'S_UCP_ACTION' => $this->u_action . "&g=$group_id",
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=usernames'),
));
@@ -896,7 +914,7 @@ class ucp_groups
if (!sizeof($mark_ary))
{
$start = 0;
-
+
do
{
$sql = 'SELECT user_id
@@ -948,6 +966,9 @@ class ucp_groups
);
}
+ // redirect to last screen
+ redirect($this->u_action . '&action=list&g=' . $group_id);
+
break;
case 'deleteusers':
@@ -994,6 +1015,9 @@ class ucp_groups
);
}
+ // redirect to last screen
+ redirect($this->u_action . '&action=list&g=' . $group_id);
+
break;
case 'addusers':
@@ -1027,7 +1051,7 @@ class ucp_groups
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
$default = request_var('default', 0);
-
+
if (confirm_box(true))
{
// Add user/s to group
diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php
index b4ac0c11da..6ac02c7d0a 100644
--- a/phpBB/includes/ucp/ucp_pm.php
+++ b/phpBB/includes/ucp/ucp_pm.php
@@ -119,7 +119,13 @@ class ucp_pm
if (!$auth->acl_get('u_sendpm'))
{
- trigger_error('NO_AUTH_SEND_MESSAGE');
+ // trigger_error('NO_AUTH_SEND_MESSAGE');
+ $template->assign_vars(array(
+ 'S_NO_AUTH_SEND_MESSAGE' => true,
+ ));
+
+ $tpl_file = 'ucp_pm_viewfolder';
+ break;
}
include($phpbb_root_path . 'includes/ucp/ucp_pm_compose.' . $phpEx);
diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php
index 008d8d6c88..1d428ce92e 100644
--- a/phpBB/includes/ucp/ucp_pm_compose.php
+++ b/phpBB/includes/ucp/ucp_pm_compose.php
@@ -46,6 +46,9 @@ function compose_pm($id, $mode, $action)
$draft_id = request_var('d', 0);
$lastclick = request_var('lastclick', 0);
+ // Reply to all triggered (quote/reply)
+ $reply_to_all = request_var('reply_to_all', 0);
+
// Do NOT use request_var or specialchars here
$address_list = isset($_REQUEST['address_list']) ? $_REQUEST['address_list'] : array();
@@ -85,6 +88,10 @@ function compose_pm($id, $mode, $action)
redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'));
}
+ // Since viewtopic.php language entries are used in several modes,
+ // we include the language file here
+ $user->add_lang('viewtopic');
+
// Output PM_TO box if message composing
if ($action != 'edit')
{
@@ -310,13 +317,14 @@ function compose_pm($id, $mode, $action)
if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !sizeof($address_list) && !$refresh && !$submit && !$preview)
{
- if ($action == 'quotepost')
+ // Add the original author as the recipient if quoting a post or only replying and not having checked "reply to all"
+ if ($action == 'quotepost' || !$reply_to_all)
{
$address_list = array('u' => array($post['author_id'] => 'to'));
}
else
{
- // We try to include every previously listed member from the TO Header
+ // We try to include every previously listed member from the TO Header - Reply to all
$address_list = rebuild_header(array('to' => $post['to_address']));
// Add the author (if he is already listed then this is no shame (it will be overwritten))
@@ -439,7 +447,7 @@ function compose_pm($id, $mode, $action)
$max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients;
// If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients
- if (($action == 'reply' || $action == 'quote') && $max_recipients)
+ if (($action == 'reply' || $action == 'quote') && $max_recipients && $reply_to_all)
{
// We try to include every previously listed member from the TO Header
$list = rebuild_header(array('to' => $post['to_address']));
@@ -631,7 +639,7 @@ function compose_pm($id, $mode, $action)
// Load Drafts
if ($load && $drafts)
{
- load_drafts(0, 0, $id);
+ load_drafts(0, 0, $id, $action, $msg_id);
}
if ($submit || $preview || $refresh)
@@ -661,7 +669,22 @@ function compose_pm($id, $mode, $action)
}
// Parse Attachments - before checksum is calculated
- $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true);
+ if ($action == 'edit')
+ {
+ $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true, $msg_id);
+ if (sizeof($message_parser->attachment_data))
+ {
+ // Update attachment indicators for pms having attachments now, as a precaution if the pm does not get stored by submit
+ $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
+ SET message_attachment = 1
+ WHERE msg_id = ' . $msg_id;
+ $db->sql_query($sql);
+ }
+ }
+ else
+ {
+ $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true);
+ }
if (sizeof($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc))
{
@@ -746,7 +769,6 @@ function compose_pm($id, $mode, $action)
// Preview
if (!sizeof($error) && $preview)
{
- $user->add_lang('viewtopic');
$preview_message = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false);
$preview_signature = $user->data['user_sig'];
@@ -1141,8 +1163,14 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove
global $refresh, $submit, $preview;
- $refresh = $preview = true;
+ $refresh = true;
$submit = false;
+
+ // Preview is only true if there was also a message entered
+ if (request_var('message', ''))
+ {
+ $preview = true;
+ }
}
// Add User/Group [TO]
diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php
index 2d2ff23cab..e80c0672cf 100644
--- a/phpBB/includes/ucp/ucp_pm_options.php
+++ b/phpBB/includes/ucp/ucp_pm_options.php
@@ -109,6 +109,10 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
$db->sql_query($sql);
$msg = $user->lang['FOLDER_ADDED'];
}
+ else
+ {
+ $msg = $user->lang['FOLDER_NAME_EMPTY'];
+ }
}
else
{
diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php
index cb96b77754..6493b54e1f 100644
--- a/phpBB/includes/ucp/ucp_pm_viewfolder.php
+++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php
@@ -115,82 +115,9 @@ function view_folder($id, $mode, $folder_id, $folder)
// Build Recipient List if in outbox/sentbox - max two additional queries
if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX)
{
- $recipient_list = $address = array();
-
- foreach ($folder_info['rowset'] as $message_id => $row)
- {
- $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address']));
- $_save = array('u', 'g');
- foreach ($_save as $save)
- {
- if (isset($address[$message_id][$save]) && sizeof($address[$message_id][$save]))
- {
- foreach (array_keys($address[$message_id][$save]) as $ug_id)
- {
- $recipient_list[$save][$ug_id] = array('name' => $user->lang['NA'], 'colour' => '');
- }
- }
- }
- }
-
- $_types = array('u', 'g');
- foreach ($_types as $ug_type)
- {
- if (!empty($recipient_list[$ug_type]))
- {
- if ($ug_type == 'u')
- {
- $sql = 'SELECT user_id as id, username as name, user_colour as colour
- FROM ' . USERS_TABLE . '
- WHERE ';
- }
- else
- {
- $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type
- FROM ' . GROUPS_TABLE . '
- WHERE ';
- }
- $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type])));
-
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- if ($ug_type == 'g')
- {
- $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name'];
- }
-
- $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
- }
- $db->sql_freeresult($result);
- }
- }
-
- foreach ($address as $message_id => $adr_ary)
- {
- foreach ($adr_ary as $type => $id_ary)
- {
- foreach ($id_ary as $ug_id => $_id)
- {
- if ($type == 'u')
- {
- $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']);
- }
- else
- {
- $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : '';
- $link = '
';
- $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '' : '');
- }
- }
- }
- }
- unset($recipient_list, $address);
+ $address_list = get_recipient_strings($folder_info['rowset']);
}
- $data = array();
-
foreach ($folder_info['pm_list'] as $message_id)
{
$row = &$folder_info['rowset'][$message_id];
@@ -267,7 +194,8 @@ function view_folder($id, $mode, $folder_id, $folder)
else
{
// Build Recipient List if in outbox/sentbox
- $address = array();
+ $address = $data = array();
+
if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX)
{
foreach ($folder_info['rowset'] as $message_id => $row)
@@ -457,12 +385,12 @@ function get_pm_from($folder_id, $folder, $user_id)
if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX)
{
$sort_by_text = array('t' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('t' => 'p.msg_id', 's' => 'p.message_subject');
+ $sort_by_sql = array('t' => 'p.message_time', 's' => array('p.message_subject', 'p.message_time'));
}
else
{
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 't' => 'p.msg_id', 's' => 'p.message_subject');
+ $sort_by_sql = array('a' => array('u.username_clean', 'p.message_time'), 't' => 'p.message_time', 's' => array('p.message_subject', 'p.message_time'));
}
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
@@ -504,8 +432,9 @@ function get_pm_from($folder_id, $folder, $user_id)
'TOTAL_MESSAGES' => (($pm_count == 1) ? $user->lang['VIEW_PM_MESSAGE'] : sprintf($user->lang['VIEW_PM_MESSAGES'], $pm_count)),
'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'POST_PM_LOCKED') : $user->img('button_pm_new', 'POST_NEW_PM'),
+ 'L_NO_MESSAGES' => (!$auth->acl_get('u_sendpm')) ? $user->lang['NO_AUTH_SEND_MESSAGE'] : $user->lang['NO_MESSAGES'],
- 'L_NO_MESSAGES' => (!$auth->acl_get('u_sendpm')) ? $user->lang['POST_PM_LOCKED'] : $user->lang['NO_MESSAGES'],
+ 'S_NO_AUTH_SEND_MESSAGE' => !$auth->acl_get('u_sendpm'),
'S_SELECT_SORT_DIR' => $s_sort_dir,
'S_SELECT_SORT_KEY' => $s_sort_key,
@@ -532,16 +461,26 @@ function get_pm_from($folder_id, $folder, $user_id)
}
// Select the sort order
- $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'ASC' : 'DESC');
+ $direction = ($sort_dir == 'd') ? 'ASC' : 'DESC';
$sql_start = max(0, $pm_count - $sql_limit - $start);
}
else
{
// Select the sort order
- $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
+ $direction = ($sort_dir == 'd') ? 'DESC' : 'ASC';
$sql_start = $start;
}
+ // Sql sort order
+ if (is_array($sort_by_sql[$sort_key]))
+ {
+ $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
+ }
+ else
+ {
+ $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction;
+ }
+
$sql = 'SELECT t.*, p.root_level, p.message_time, p.message_subject, p.icon_id, p.to_address, p.message_attachment, p.bcc_address, u.username, u.username_clean, u.user_colour
FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
WHERE t.user_id = $user_id
diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php
index 5fef30056f..26968e1382 100644
--- a/phpBB/includes/ucp/ucp_pm_viewmessage.php
+++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php
@@ -29,6 +29,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
$msg_id = (int) $msg_id;
$folder_id = (int) $folder_id;
$author_id = (int) $message_row['author_id'];
+ $view = request_var('view', '');
// Not able to view message, it was deleted by the sender
if ($message_row['pm_deleted'])
@@ -168,6 +169,9 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
$url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
+ // Number of "to" recipients
+ $num_recipients = (int) preg_match_all('/:?(u|g)_([0-9]+):?/', $message_row['to_address'], $match);
+
$template->assign_vars(array(
'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']),
'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']),
@@ -178,7 +182,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'RANK_IMG' => $user_info['rank_image'],
'AUTHOR_AVATAR' => (isset($user_info['avatar'])) ? $user_info['avatar'] : '',
'AUTHOR_JOINED' => $user->format_date($user_info['user_regdate']),
- 'AUTHOR_POSTS' => (!empty($user_info['user_posts'])) ? $user_info['user_posts'] : '',
+ 'AUTHOR_POSTS' => (int) $user_info['user_posts'],
'AUTHOR_FROM' => (!empty($user_info['user_from'])) ? $user_info['user_from'] : '',
'ONLINE_IMG' => (!$config['load_onlinetrack']) ? '' : ((isset($user_info['online']) && $user_info['online']) ? $user->img('icon_user_online', $user->lang['ONLINE']) : $user->img('icon_user_offline', $user->lang['OFFLINE'])),
@@ -189,10 +193,11 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['SEND_EMAIL']),
'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['POST_QUOTE_PM']),
'REPLY_IMG' => $user->img('button_pm_reply', $user->lang['POST_REPLY_PM']),
+ 'REPORT_IMG' => $user->img('icon_post_report', 'REPORT_PM'),
'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['POST_EDIT_PM']),
'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']),
- 'SENT_DATE' => $user->format_date($message_row['message_time']),
+ 'SENT_DATE' => ($view == 'print') ? $user->format_date($message_row['message_time'], false, true) : $user->format_date($message_row['message_time']),
'SUBJECT' => $message_row['message_subject'],
'MESSAGE' => $message,
'SIGNATURE' => ($message_row['enable_sig']) ? $signature : '',
@@ -209,16 +214,21 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '',
'U_EMAIL' => $user_info['email'],
+ 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '',
'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '',
'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '',
'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '',
+ 'U_POST_REPLY_ALL' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&reply_to_all=1&p=" . $message_row['msg_id'] : '',
'U_PREVIOUS_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=previous",
'U_NEXT_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=next",
+ 'U_PM_ACTION' => $url . '&mode=compose&f=' . $folder_id . '&p=' . $message_row['msg_id'],
+
'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false,
'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'],
'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false,
'S_SPECIAL_FOLDER' => in_array($folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)),
+ 'S_PM_RECIPIENTS' => $num_recipients,
'U_PRINT_PM' => ($config['print_pm'] && $auth->acl_get('u_pm_printpm')) ? "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=print" : '',
'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&mode=compose&action=forward&f=$folder_id&p=" . $message_row['msg_id'] : '')
diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php
index 9b705fba6c..cc8565e69d 100644
--- a/phpBB/includes/ucp/ucp_prefs.php
+++ b/phpBB/includes/ucp/ucp_prefs.php
@@ -282,7 +282,7 @@ class ucp_prefs
'S_AVATARS' => $data['avatars'],
'S_DISABLE_CENSORS' => $data['wordcensor'],
- 'S_CHANGE_CENSORS' => ($auth->acl_get('u_chgcensors')) ? true : false,
+ 'S_CHANGE_CENSORS' => ($auth->acl_get('u_chgcensors') && $config['allow_nocensors']) ? true : false,
'S_TOPIC_SORT_DAYS' => $s_limit_topic_days,
'S_TOPIC_SORT_KEY' => $s_sort_topic_key,
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index 30752d8c8a..e24acd89fc 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -110,7 +110,7 @@ class ucp_profile
'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'],
'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'],
'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'],
- 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? crc32($data['email']) . strlen($data['email']) : $user->data['user_email_hash'],
+ 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? phpbb_email_hash($data['email']) : $user->data['user_email_hash'],
'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? phpbb_hash($data['new_password']) : $user->data['user_password'],
'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0,
);
@@ -380,25 +380,7 @@ class ucp_profile
$db->sql_query($sql);
// Update Custom Fields
- if (sizeof($cp_data))
- {
- $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . '
- SET ' . $db->sql_build_array('UPDATE', $cp_data) . '
- WHERE user_id = ' . $user->data['user_id'];
- $db->sql_query($sql);
-
- if (!$db->sql_affectedrows())
- {
- $cp_data['user_id'] = (int) $user->data['user_id'];
-
- $db->sql_return_on_error(true);
-
- $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data);
- $db->sql_query($sql);
-
- $db->sql_return_on_error(false);
- }
- }
+ $cp->update_profile_field_data($user->data['user_id'], $cp_data);
meta_refresh(3, $this->u_action);
$message = $user->lang['PROFILE_UPDATED'] . '
' . sprintf($user->lang['RETURN_UCP'], '
', '');
@@ -474,9 +456,9 @@ class ucp_profile
include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
- $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', !$user->optionget('bbcode'))) ? false : true) : false;
- $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', !$user->optionget('smilies'))) ? false : true) : false;
- $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $user->optionget('sig_bbcode') : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $user->optionget('sig_smilies') : false;
+ $enable_urls = ($config['allow_sig_links']) ? (bool) $user->optionget('sig_links') : false;
$signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true));
@@ -486,6 +468,10 @@ class ucp_profile
{
include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false;
+ $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false;
+ $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false;
+
if (!sizeof($error))
{
$message_parser = new parse_message($signature);
@@ -505,8 +491,13 @@ class ucp_profile
if (!sizeof($error) && $submit)
{
+ $user->optionset('sig_bbcode', $enable_bbcode);
+ $user->optionset('sig_smilies', $enable_smilies);
+ $user->optionset('sig_links', $enable_urls);
+
$sql_ary = array(
'user_sig' => (string) $message_parser->message,
+ 'user_options' => $user->data['user_options'],
'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield
);
@@ -573,7 +564,7 @@ class ucp_profile
$avatar_select = basename(request_var('avatar_select', ''));
$category = basename(request_var('category', ''));
- $can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;
+ $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;
add_form_key('ucp_avatar');
@@ -596,33 +587,44 @@ class ucp_profile
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
+ if (!$config['allow_avatar'] && $user->data['user_avatar_type'])
+ {
+ $error[] = $user->lang['AVATAR_NOT_ALLOWED'];
+ }
+ else if ((($user->data['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) ||
+ (($user->data['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) ||
+ (($user->data['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local']))
+ {
+ $error[] = $user->lang['AVATAR_TYPE_NOT_ALLOWED'];
+ }
+
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('
', $error) : '',
- 'AVATAR' => get_user_avatar($user->data['user_avatar'], $user->data['user_avatar_type'], $user->data['user_avatar_width'], $user->data['user_avatar_height']),
+ 'AVATAR' => get_user_avatar($user->data['user_avatar'], $user->data['user_avatar_type'], $user->data['user_avatar_width'], $user->data['user_avatar_height'], 'USER_AVATAR', true),
'AVATAR_SIZE' => $config['avatar_filesize'],
'U_GALLERY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&mode=avatar&display_gallery=1'),
- 'S_FORM_ENCTYPE' => ($can_upload) ? ' enctype="multipart/form-data"' : '',
+ 'S_FORM_ENCTYPE' => ($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) ? ' enctype="multipart/form-data"' : '',
'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024),
));
- if ($display_gallery && $auth->acl_get('u_chgavatar') && $config['allow_avatar_local'])
+ if ($config['allow_avatar'] && $display_gallery && $auth->acl_get('u_chgavatar') && $config['allow_avatar_local'])
{
avatar_gallery($category, $avatar_select, 4);
}
- else
+ else if ($config['allow_avatar'])
{
- $avatars_enabled = ($can_upload || ($auth->acl_get('u_chgavatar') && ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false;
+ $avatars_enabled = (($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) || ($auth->acl_get('u_chgavatar') && ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false;
$template->assign_vars(array(
'AVATAR_WIDTH' => request_var('width', $user->data['user_avatar_width']),
'AVATAR_HEIGHT' => request_var('height', $user->data['user_avatar_height']),
'S_AVATARS_ENABLED' => $avatars_enabled,
- 'S_UPLOAD_AVATAR_FILE' => $can_upload,
- 'S_UPLOAD_AVATAR_URL' => $can_upload,
+ 'S_UPLOAD_AVATAR_FILE' => ($can_upload && $config['allow_avatar_upload']) ? true : false,
+ 'S_UPLOAD_AVATAR_URL' => ($can_upload && $config['allow_avatar_remote_upload']) ? true : false,
'S_LINK_AVATAR' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_remote']) ? true : false,
'S_DISPLAY_GALLERY' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) ? true : false)
);
diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php
index e42ad8369d..8359c223e0 100644
--- a/phpBB/includes/ucp/ucp_register.php
+++ b/phpBB/includes/ucp/ucp_register.php
@@ -37,13 +37,11 @@ class ucp_register
include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx);
- $confirm_id = request_var('confirm_id', '');
- $confirm_refresh = (isset($_POST['confirm_refresh']) && $config['confirm_refresh']) ? ((!empty($_POST['confirm_refresh'])) ? 1 : 0) : false;
- $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false;
- $agreed = (!empty($_POST['agreed'])) ? 1 : 0;
- $submit = (isset($_POST['submit'])) ? true : false;
- $change_lang = request_var('change_lang', '');
- $user_lang = request_var('lang', $user->lang_name);
+ $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false;
+ $agreed = (!empty($_POST['agreed'])) ? 1 : 0;
+ $submit = (isset($_POST['submit'])) ? true : false;
+ $change_lang = request_var('change_lang', '');
+ $user_lang = request_var('lang', $user->lang_name);
if ($agreed)
{
@@ -54,7 +52,6 @@ class ucp_register
add_form_key('ucp_register_terms');
}
-
if ($change_lang || $user_lang != $config['default_lang'])
{
$use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang);
@@ -69,8 +66,9 @@ class ucp_register
$agreed = (empty($_GET['change_lang'])) ? 0 : $agreed;
}
- $user->lang_name = $lang = $use_lang;
+ $user->lang_name = $user_lang = $use_lang;
$user->lang = array();
+ $user->data['user_lang'] = $user->lang_name;
$user->add_lang(array('common', 'ucp'));
}
else
@@ -80,17 +78,19 @@ class ucp_register
}
}
+
$cp = new custom_profile();
$error = $cp_data = $cp_error = array();
-
if (!$agreed || ($coppa === false && $config['coppa_enable']) || ($coppa && !$config['coppa_enable']))
{
$add_lang = ($change_lang) ? '&change_lang=' . urlencode($change_lang) : '';
$add_coppa = ($coppa !== false) ? '&coppa=' . $coppa : '';
- $s_hidden_fields = ($confirm_id) ? array('confirm_id' => $confirm_id) : array();
+ $s_hidden_fields = array(
+ 'change_lang' => $change_lang,
+ );
// If we change the language, we want to pass on some more possible parameter.
if ($change_lang)
@@ -100,13 +100,24 @@ class ucp_register
'username' => utf8_normalize_nfc(request_var('username', '', true)),
'email' => strtolower(request_var('email', '')),
'email_confirm' => strtolower(request_var('email_confirm', '')),
- 'confirm_code' => request_var('confirm_code', ''),
- 'confirm_id' => request_var('confirm_id', ''),
'lang' => $user->lang_name,
'tz' => request_var('tz', (float) $config['board_timezone']),
));
+
}
+ // Checking amount of available languages
+ $sql = 'SELECT lang_id
+ FROM ' . LANG_TABLE;
+ $result = $db->sql_query($sql);
+
+ $lang_row = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $lang_row[] = $row;
+ }
+ $db->sql_freeresult($result);
+
if ($coppa === false && $config['coppa_enable'])
{
$now = getdate();
@@ -114,6 +125,7 @@ class ucp_register
unset($now);
$template->assign_vars(array(
+ 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '',
'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday),
'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday),
@@ -128,6 +140,7 @@ class ucp_register
else
{
$template->assign_vars(array(
+ 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '',
'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()),
'S_SHOW_COPPA' => false,
@@ -137,11 +150,20 @@ class ucp_register
)
);
}
+ unset($lang_row);
$this->tpl_name = 'ucp_agreement';
return;
}
-
+
+
+ // The CAPTCHA kicks in here. We can't help that the information gets lost on language change.
+ if ($config['enable_confirm'])
+ {
+ include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
+ $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']);
+ $captcha->init(CONFIRM_REG);
+ }
// Try to manually determine the timezone and adjust the dst if the server date/time complies with the default setting +/- 1
$timezone = date('Z') / 3600;
@@ -168,7 +190,6 @@ class ucp_register
'password_confirm' => request_var('password_confirm', '', true),
'email' => strtolower(request_var('email', '')),
'email_confirm' => strtolower(request_var('email_confirm', '')),
- 'confirm_code' => request_var('confirm_code', ''),
'lang' => basename(request_var('lang', $user->lang_name)),
'tz' => request_var('tz', (float) $timezone),
);
@@ -188,17 +209,32 @@ class ucp_register
array('string', false, 6, 60),
array('email')),
'email_confirm' => array('string', false, 6, 60),
- 'confirm_code' => array('string', !$config['enable_confirm'], CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS),
'tz' => array('num', false, -14, 14),
'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
));
+
if (!check_form_key('ucp_register'))
{
$error[] = $user->lang['FORM_INVALID'];
}
+
// Replace "error" strings with their real, localised form
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
+ if ($config['enable_confirm'])
+ {
+ $vc_response = $captcha->validate($data);
+ if ($vc_response !== false)
+ {
+ $error[] = $vc_response;
+ }
+
+ if ($config['max_reg_attempts'] && $captcha->get_attempt_count() > $config['max_reg_attempts'])
+ {
+ $error[] = $user->lang['TOO_MANY_REGISTERS'];
+ }
+ }
+
// DNSBL check
if ($config['check_dnsbl'])
{
@@ -211,50 +247,6 @@ class ucp_register
// validate custom profile fields
$cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error);
- // Visual Confirmation handling
- $wrong_confirm = false;
- if ($config['enable_confirm'])
- {
- if (!$confirm_id)
- {
- $error[] = $user->lang['CONFIRM_CODE_WRONG'];
- $wrong_confirm = true;
- }
- else
- {
- $sql = 'SELECT code
- FROM ' . CONFIRM_TABLE . "
- WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_REG;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- if (strcasecmp($row['code'], $data['confirm_code']) === 0)
- {
- $sql = 'DELETE FROM ' . CONFIRM_TABLE . "
- WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_REG;
- $db->sql_query($sql);
- }
- else
- {
- $error[] = $user->lang['CONFIRM_CODE_WRONG'];
- $wrong_confirm = true;
- }
- }
- else
- {
- $error[] = $user->lang['CONFIRM_CODE_WRONG'];
- $wrong_confirm = true;
- }
- }
- }
-
if (!sizeof($error))
{
if ($data['new_password'] != $data['password_confirm'])
@@ -327,6 +319,11 @@ class ucp_register
'user_inactive_time' => $user_inactive_time,
);
+ if ($config['new_member_post_limit'])
+ {
+ $user_row['user_new'] = 1;
+ }
+
// Register user...
$user_id = user_add($user_row, $cp_data);
@@ -441,85 +438,20 @@ class ucp_register
{
$s_hidden_fields['coppa'] = $coppa;
}
- $s_hidden_fields = build_hidden_fields($s_hidden_fields);
-
- $confirm_image = '';
-
- // Visual Confirmation - Show images
if ($config['enable_confirm'])
{
- if ($change_lang || $confirm_refresh)
- {
- $str = '&change_lang=' . $change_lang;
- $sql = 'SELECT code
- FROM ' . CONFIRM_TABLE . "
- WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
- AND session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_REG;
- $result = $db->sql_query($sql);
- if (!$row = $db->sql_fetchrow($result))
- {
- $confirm_id = '';
- }
- $db->sql_freeresult($result);
- }
- else
- {
- $str = '';
- }
- if (!$change_lang || !$confirm_id || !$confirm_refresh)
- {
- $user->confirm_gc(CONFIRM_REG);
+ $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields());
+ }
+ $s_hidden_fields = build_hidden_fields($s_hidden_fields);
+ $confirm_image = '';
- $sql = 'SELECT COUNT(session_id) AS attempts
- FROM ' . CONFIRM_TABLE . "
- WHERE session_id = '" . $db->sql_escape($user->session_id) . "'
- AND confirm_type = " . CONFIRM_REG;
- $result = $db->sql_query($sql);
- $attempts = (int) $db->sql_fetchfield('attempts');
- $db->sql_freeresult($result);
-
- if ($config['max_reg_attempts'] && $attempts > $config['max_reg_attempts'])
- {
- trigger_error('TOO_MANY_REGISTERS');
- }
-
- $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
- $confirm_id = md5(unique_id($user->ip));
- $seed = hexdec(substr(unique_id(), 4, 10));
-
- // compute $seed % 0x7fffffff
- $seed -= 0x7fffffff * floor($seed / 0x7fffffff);
-
- $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'confirm_id' => (string) $confirm_id,
- 'session_id' => (string) $user->session_id,
- 'confirm_type' => (int) CONFIRM_REG,
- 'code' => (string) $code,
- 'seed' => (int) $seed)
- );
- $db->sql_query($sql);
- }
- else if ($confirm_refresh)
- {
- $code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
- $confirm_id = md5(unique_id($user->ip));
- $seed = hexdec(substr(unique_id(), 4, 10));
- // compute $seed % 0x7fffffff
- $seed -= 0x7fffffff * floor($seed / 0x7fffffff);
- $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
- 'confirm_type' => (int) CONFIRM_REG,
- 'code' => (string) $code,
- 'seed' => (int) $seed)) . "
- WHERE
- confirm_id = '" . $db->sql_escape($confirm_id) . "' AND
- session_id = '" . $db->sql_escape($session_id) . "' AND
- confirm_type = " . (int) CONFIRM_REG;
- $db->sql_query($sql);
- }
- $confirm_image = '

';
- $s_hidden_fields .= '
';
+ // Visual Confirmation - Show images
+ if ($config['enable_confirm'])
+ {
+ $template->assign_vars(array(
+ 'CAPTCHA_TEMPLATE' => $captcha->get_template(),
+ ));
}
//
@@ -542,22 +474,19 @@ class ucp_register
'PASSWORD_CONFIRM' => $data['password_confirm'],
'EMAIL' => $data['email'],
'EMAIL_CONFIRM' => $data['email_confirm'],
- 'CONFIRM_IMG' => $confirm_image,
- 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '
', ''),
'L_REG_COND' => $l_reg_cond,
'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']),
'L_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
'S_LANG_OPTIONS' => language_select($data['lang']),
'S_TZ_OPTIONS' => tz_select($data['tz']),
- 'S_CONFIRM_CODE' => ($config['enable_confirm']) ? true : false,
'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false,
+ 'S_REGISTRATION' => true,
'S_COPPA' => $coppa,
'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'),
- )
- );
+ ));
//
$user->profile_fields = array();
diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php
index 6325bf89b6..df6733d038 100644
--- a/phpBB/includes/ucp/ucp_remind.php
+++ b/phpBB/includes/ucp/ucp_remind.php
@@ -38,7 +38,7 @@ class ucp_remind
{
$sql = 'SELECT user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason
FROM ' . USERS_TABLE . "
- WHERE user_email = '" . $db->sql_escape($email) . "'
+ WHERE user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "'
AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php
index cad494541b..39e9be24a1 100644
--- a/phpBB/includes/ucp/ucp_resend.php
+++ b/phpBB/includes/ucp/ucp_resend.php
@@ -45,7 +45,7 @@ class ucp_resend
$sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey, user_inactive_reason
FROM ' . USERS_TABLE . "
- WHERE user_email = '" . $db->sql_escape($email) . "'
+ WHERE user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "'
AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php
index fb5df9394b..5ed4db7520 100644
--- a/phpBB/includes/ucp/ucp_zebra.php
+++ b/phpBB/includes/ucp/ucp_zebra.php
@@ -52,6 +52,18 @@ class ucp_zebra
{
if (confirm_box(true))
{
+ // Remove users
+ if (!empty($data['usernames']))
+ {
+ $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
+ WHERE user_id = ' . $user->data['user_id'] . '
+ AND ' . $db->sql_in_set('zebra_id', $data['usernames']);
+ $db->sql_query($sql);
+
+ $updated = true;
+ }
+
+ // Add users
if ($data['add'])
{
$data['add'] = array_map('trim', array_map('utf8_clean_string', explode("\n", $data['add'])));
@@ -124,6 +136,10 @@ class ucp_zebra
{
$user_id_ary[] = $row['user_id'];
}
+ else if ($row['user_id'] != ANONYMOUS)
+ {
+ $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_BOTS'];
+ }
else
{
$error[] = $user->lang['NOT_ADDED_' . $l_mode . '_ANONYMOUS'];
@@ -183,18 +199,6 @@ class ucp_zebra
}
}
}
- else if (sizeof($data['usernames']))
- {
- // Force integer values
- $data['usernames'] = array_map('intval', $data['usernames']);
-
- $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
- WHERE user_id = ' . $user->data['user_id'] . '
- AND ' . $db->sql_in_set('zebra_id', $data['usernames']);
- $db->sql_query($sql);
-
- $updated = true;
- }
if ($updated)
{
diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php
index 8098176837..6f3ac93305 100644
--- a/phpBB/includes/utf/utf_tools.php
+++ b/phpBB/includes/utf/utf_tools.php
@@ -70,7 +70,7 @@ if (!extension_loaded('xml'))
$pos = 0;
$len = strlen($str);
$ret = '';
-
+
while ($pos < $len)
{
$ord = ord($str[$pos]) & 0xF0;
@@ -252,7 +252,7 @@ else
if (is_null($offset))
{
$ar = explode($needle, $str);
-
+
if (sizeof($ar) > 1)
{
// Pop off the end of the string where the last match was made
@@ -527,7 +527,7 @@ else
$op = '^(?:' . $op . '.{' . $oy . '})';
}
else
- {
+ {
// offset == 0; just anchor the pattern
$op = '^';
}
@@ -560,7 +560,7 @@ else
$lx = (int) ($length / 65535);
$ly = $length % 65535;
-
+
// negative length requires a captured group
// of length characters
if ($lx)
@@ -632,7 +632,7 @@ function utf8_str_split($str, $split_len = 1)
{
return array($str);
}
-
+
preg_match_all('/.{' . $split_len . '}|[^\x00]{1,' . $split_len . '}$/us', $str, $ar);
return $ar[0];
}
@@ -1917,4 +1917,79 @@ function utf8_wordwrap($string, $width = 75, $break = "\n", $cut = false)
return implode($break, $new_lines);
}
+/**
+* UTF8-safe basename() function
+*
+* basename() has some limitations and is dependent on the locale setting
+* according to the PHP manual. Therefore we provide our own locale independant
+* basename function.
+*
+* @param string $filename The filename basename() should be applied to
+* @return string The basenamed filename
+*/
+function utf8_basename($filename)
+{
+ // We always check for forward slash AND backward slash
+ // because they could be mixed or "sneaked" in. ;)
+ // You know, never trust user input...
+ if (strpos($filename, '/') !== false)
+ {
+ $filename = utf8_substr($filename, utf8_strrpos($filename, '/') + 1);
+ }
+
+ if (strpos($filename, '\\') !== false)
+ {
+ $filename = utf8_substr($filename, utf8_strrpos($filename, '\\') + 1);
+ }
+
+ return $filename;
+}
+
+/**
+* UTF8-safe str_replace() function
+*
+* @param string $search The value to search for
+* @param string $replace The replacement string
+* @param string $subject The target string
+* @return string The resultant string
+*/
+function utf8_str_replace($search, $replace, $subject)
+{
+ if (!is_array($search))
+ {
+ $search = array($search);
+ if (is_array($replace))
+ {
+ $replace = (string) $replace;
+ trigger_error('Array to string conversion', E_USER_NOTICE);
+ }
+ }
+
+ $length = sizeof($search);
+
+ if (!is_array($replace))
+ {
+ $replace = array_fill(0, $length, $replace);
+ }
+ else
+ {
+ $replace = array_pad($replace, $length, '');
+ }
+
+ for ($i = 0; $i < $length; $i++)
+ {
+ $search_length = utf8_strlen($search[$i]);
+ $replace_length = utf8_strlen($replace[$i]);
+
+ $offset = 0;
+ while (($start = utf8_strpos($subject, $search[$i], $offset)) !== false)
+ {
+ $subject = utf8_substr($subject, 0, $start) . $replace[$i] . utf8_substr($subject, $start + $search_length);
+ $offset = $start + $replace_length;
+ }
+ }
+
+ return $subject;
+}
+
?>
\ No newline at end of file
diff --git a/phpBB/index.php b/phpBB/index.php
index 2d1329c511..c3dbbd346e 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -84,10 +84,13 @@ $birthday_list = '';
if ($config['load_birthdays'] && $config['allow_birthdays'])
{
$now = getdate(time() + $user->timezone + $user->dst - date('Z'));
- $sql = 'SELECT user_id, username, user_colour, user_birthday
- FROM ' . USERS_TABLE . "
- WHERE user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%'
- AND user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
+ $sql = 'SELECT u.user_id, u.username, u.user_colour, u.user_birthday
+ FROM ' . USERS_TABLE . ' u
+ LEFT JOIN ' . BANLIST_TABLE . " b ON (u.user_id = b.ban_userid)
+ WHERE (b.ban_id IS NULL
+ OR b.ban_exclude = 1)
+ AND u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%'
+ AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
index 805c67b92d..f4fc466ac7 100644
--- a/phpBB/install/convertors/convert_phpbb20.php
+++ b/phpBB/install/convertors/convert_phpbb20.php
@@ -611,6 +611,7 @@ if (!$get_info)
'query_first' => array('target', $convert->truncate_statement . POSTS_TABLE),
'execute_first' => '
$config["max_post_chars"] = 0;
+ $config["min_post_chars"] = 0;
$config["max_quote_depth"] = 0;
',
@@ -660,6 +661,7 @@ if (!$get_info)
'execute_first' => '
$config["max_post_chars"] = 0;
+ $config["min_post_chars"] = 0;
$config["max_quote_depth"] = 0;
',
diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php
index 124bbe83ce..b80c7673e3 100644
--- a/phpBB/install/convertors/functions_phpbb20.php
+++ b/phpBB/install/convertors/functions_phpbb20.php
@@ -71,8 +71,8 @@ function phpbb_insert_forums()
$result = $src_db->sql_query($sql);
$prune_enabled = (int) $src_db->sql_fetchfield('config_value');
$src_db->sql_freeresult($result);
-
-
+
+
// Insert categories
$sql = 'SELECT cat_id, cat_title
FROM ' . $convert->src_table_prefix . 'categories
@@ -227,6 +227,7 @@ function phpbb_insert_forums()
'prune_freq' => (int) null_to_zero($row['prune_freq']),
'forum_flags' => phpbb_forum_flags(),
+ 'forum_options' => 0,
// Default values
'forum_desc_bitfield' => '',
@@ -972,12 +973,12 @@ function phpbb_convert_authentication($mode)
{
// And now the moderators
// We make sure that they have at least standard access to the forums they moderate in addition to the moderating permissions
-
+
$mod_post_map = array(
'auth_announce' => 'f_announce',
'auth_sticky' => 'f_sticky'
);
-
+
foreach ($user_access as $forum_id => $access_map)
{
$forum_id = (int) $forum_id;
@@ -1229,7 +1230,7 @@ function phpbb_prepare_message($message)
{
$message = preg_replace('/\[quote="(.*?)"\]/s', '[quote="\1"]', $message);
$message = preg_replace('/\[quote=\\\"(.*?)\\\"\]/s', '[quote="\1"]', $message);
-
+
// let's hope that this solves more problems than it causes. Deal with escaped quotes.
$message = str_replace('\"', '"', $message);
$message = str_replace('\"', '"', $message);
@@ -1258,7 +1259,7 @@ function phpbb_prepare_message($message)
// parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post')
$message_parser->parse($enable_bbcode, $enable_magic_url, $enable_smilies);
-
+
if (sizeof($message_parser->warn_msg))
{
$msg_id = isset($convert->row['post_id']) ? $convert->row['post_id'] : $convert->row['privmsgs_id'];
@@ -1352,7 +1353,7 @@ function phpbb_copy_thumbnails()
global $db, $convert, $user, $config, $cache, $phpbb_root_path;
$src_path = $convert->options['forum_path'] . '/' . phpbb_get_files_dir() . '/thumbs/';
-
+
if ($handle = @opendir($src_path))
{
while ($entry = readdir($handle))
@@ -1431,13 +1432,13 @@ function phpbb_attachment_forum_perms($forum_permissions)
$pos--;
continue;
}
-
+
$forum_auth = substr($forum_permissions, $pos, $auth_len);
$forum_id = base64_unpack($forum_auth);
$forum_ids[] = (int) $forum_id;
}
-
+
if (sizeof($forum_ids))
{
return attachment_forum_perms($forum_ids);
@@ -1516,7 +1517,7 @@ function phpbb_import_avatar($user_avatar)
function phpbb_get_avatar_height($user_avatar)
{
global $convert_row;
-
+
if (empty($convert_row['user_avatar_type']))
{
return 0;
@@ -1536,7 +1537,7 @@ function phpbb_get_avatar_width($user_avatar)
{
return 0;
}
-
+
return get_avatar_width($user_avatar, 'phpbb_avatar_type', $convert_row['user_avatar_type']);
}
@@ -1708,7 +1709,7 @@ function phpbb_create_userconv_table()
case 'mysql':
$map_dbms = 'mysql_40';
break;
-
+
case 'mysql4':
if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
{
@@ -1719,16 +1720,16 @@ function phpbb_create_userconv_table()
$map_dbms = 'mysql_40';
}
break;
-
+
case 'mysqli':
$map_dbms = 'mysql_41';
break;
-
+
case 'mssql':
case 'mssql_odbc':
$map_dbms = 'mssql';
break;
-
+
default:
$map_dbms = $db->sql_layer;
break;
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index c66ac859cf..41983400fc 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -8,11 +8,14 @@
*
*/
-$updates_to_version = '3.0.5';
+$updates_to_version = '3.0.6-RC1';
// Enter any version to update from to test updates. The version within the db will not be updated.
$debug_from_version = false;
+// Which oldest version does this updater support?
+$oldest_from_version = '3.0.0';
+
// Return if we "just include it" to find out for which version the database update is responsible for
if (defined('IN_PHPBB') && defined('IN_INSTALL'))
{
@@ -219,6 +222,33 @@ if (empty($config['dbms_version']))
set_config('dbms_version', $db->sql_server_info(true));
}
+// Firebird update from Firebord 2.0 to 2.1+ required?
+if ($db->sql_layer == 'firebird')
+{
+ // We do not trust any PHP5 function enabled, we will simply test for a function new in 2.1
+ $db->sql_return_on_error(true);
+
+ $sql = 'SELECT 1 FROM RDB$DATABASE
+ WHERE BIN_AND(10, 1) = 0';
+ $result = $db->sql_query($sql);
+
+ if (!$result || $db->sql_error_triggered)
+ {
+ echo '
';
+ echo '
' . $lang['ERROR'] . '
';
+
+ echo '
' . $lang['FIREBIRD_DBMS_UPDATE_REQUIRED'] . '
';
+
+ _print_footer();
+
+ exit_handler();
+ exit;
+ }
+
+ $db->sql_freeresult($result);
+ $db->sql_return_on_error(false);
+}
+
// MySQL update from MySQL 3.x/4.x to > 4.1.x required?
if ($db->sql_layer == 'mysql' || $db->sql_layer == 'mysql4' || $db->sql_layer == 'mysqli')
{
@@ -246,28 +276,25 @@ if ($db->sql_layer == 'mysql' || $db->sql_layer == 'mysql4' || $db->sql_layer ==
echo '
' . $lang['ERROR'] . '
';
echo '
' . sprintf($lang['MYSQL_SCHEMA_UPDATE_REQUIRED'], $config['dbms_version'], $db->sql_server_info(true)) . '
';
-?>
-
-
-