diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index bdb0cab..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,17 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
-
-# Custom for Visual Studio
-*.cs diff=csharp
-
-# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5f45f8a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+# phpBB mChat Extension
+
+## Install
+
+1. Download the latest release.
+2. Unzip the downloaded release, and change the name of the folder to `mchat`.
+3. In the `ext` directory of your phpBB board, create a new directory named `dmzx` (if it does not already exist).
+4. Copy the `mchat` folder to `/ext/dmzx/` (if done correctly, you'll have the main extension class at (your forum root)/ext/dmzx/mchat/composer.json).
+5. Navigate in the ACP to `Customise -> Manage extensions`.
+6. Look for `mChat` under the Disabled Extensions list, and click its `Enable` link.
+
+## Uninstall
+
+1. Navigate in the ACP to `Customise -> Extension Management -> Extensions`.
+2. Look for `mChat` under the Enabled Extensions list, and click its `Disable` link.
+3. To permanently uninstall, click `Delete Data` and then delete the `/ext/dmzx/mchat` folder.
+
+## License
+[GNU General Public License v2](http://opensource.org/licenses/GPL-2.0)
diff --git a/acp/acp_mchat_info.php b/acp/acp_mchat_info.php
new file mode 100644
index 0000000..c50fff2
--- /dev/null
+++ b/acp/acp_mchat_info.php
@@ -0,0 +1,28 @@
+ '\dmzx\mchat\acp\acp_mchat_module',
+ 'title' => 'ACP_CAT_MCHAT',
+ 'modes' => array(
+ 'configuration' => array(
+ 'title' => 'ACP_MCHAT_CONFIG',
+ 'auth' => 'ext_dmzx/mchat && acl_a_mchat',
+ 'cat' => array('ACP_CAT_MCHAT')
+ ),
+ ),
+ );
+ }
+}
diff --git a/acp/acp_mchat_module.php b/acp/acp_mchat_module.php
new file mode 100644
index 0000000..13f4257
--- /dev/null
+++ b/acp/acp_mchat_module.php
@@ -0,0 +1,257 @@
+functions_mchat = $phpbb_container->get('dmzx.mchat.functions_mchat');
+ $this->config = $config;
+ $this->config_text = $phpbb_container->get('config_text');
+ $this->db = $db;
+
+ $this->request = $request;
+ $this->template = $template;
+ $this->user = $user;
+ $this->cache = $cache;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $phpEx;
+ $this->table_prefix = $phpbb_container->getParameter('core.table_prefix');
+
+
+ // Add the wpm ACP lang file
+ $user->add_lang_ext('dmzx/mchat', 'info_acp_mchat');
+
+ // Load a template from adm/style for our ACP page
+ $this->tpl_name = 'acp_mchat';
+
+ // Set the page title for our ACP page
+ $this->page_title = 'MCHAT_TITLE';
+
+ // Define the name of the form for use as a form key
+ $form_name = 'acp_mchat';
+ add_form_key($form_name);
+
+ // something was submitted
+ $submit = (isset($_POST['submit'])) ? true : false;
+
+ $mchat_row = array(
+ 'location' => request_var('mchat_location', 0),
+ 'refresh' => request_var('mchat_refresh', 0),
+ 'message_limit' => request_var('mchat_message_limit', 0),
+ 'message_num' => request_var('mchat_message_num', 0),
+ 'archive_limit' => request_var('mchat_archive_limit', 0),
+ 'flood_time' => request_var('mchat_flood_time', 0),
+ 'max_message_lngth' => request_var('mchat_max_message_lngth', 0),
+ 'custom_page' => request_var('mchat_custom_page', 0),
+ 'date' => request_var('mchat_date', '', true),
+ 'whois' => request_var('mchat_whois', 0),
+ 'whois_refresh' => request_var('mchat_whois_refresh', 0),
+ 'bbcode_disallowed' => utf8_normalize_nfc(request_var('mchat_bbcode_disallowed', '', true)),
+ 'prune_enable' => request_var('mchat_prune_enable', 0),
+ 'prune_num' => request_var('mchat_prune_num', 0),
+ 'index_height' => request_var('mchat_index_height', 0),
+ 'custom_height' => request_var('mchat_custom_height', 0),
+ 'static_message' => utf8_normalize_nfc(request_var('mchat_static_message', '', true)),
+ 'override_min_post_chars' => request_var('mchat_override_min_post_chars', 0),
+ 'override_smilie_limit' => request_var('mchat_override_smilie_limit', 0),
+ 'timeout' => request_var('mchat_timeout', 0),
+ 'pause_on_input' => request_var('mchat_pause_on_input', 0),
+ 'rules' => utf8_normalize_nfc(request_var('mchat_rules', '', true)),
+ 'avatars' => request_var('mchat_avatars', 0),
+ );
+
+ if ($submit)
+ {
+ if (!function_exists('validate_data'))
+ {
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ }
+
+ // validate the entries...most of them anyway
+ $mchat_array = array(
+ 'static_message' => array('string', false, 0, 255),
+ 'index_height' => array('num', false, 50, 1000),
+ 'custom_height' => array('num', false, 50, 1000),
+ 'whois_refresh' => array('num', false, 30, 300),
+ 'refresh' => array('num', false, 5, 60),
+ 'message_limit' => array('num', false, 10, 30),
+ 'message_num' => array('num', false, 10, 50),
+ 'archive_limit' => array('num', false, 25, 50),
+ 'flood_time' => array('num', false, 0, 30),
+ 'max_message_lngth' => array('num', false, 0, 500),
+ 'timeout' => array('num', false, 0, (int) $config['session_length']),
+ 'rules' => array('string', false, 0, 255),
+ );
+
+ $error = validate_data($mchat_row, $mchat_array);
+
+ if (!check_form_key('acp_mchat'))
+ {
+ $error[] = '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 (!sizeof($error))
+ {
+ foreach ($mchat_row as $config_name => $config_value)
+ {
+ $sql = 'UPDATE ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_CONFIG_TABLE . "
+ SET config_value = '" . $db->sql_escape($config_value) . "'
+ WHERE config_name = '" . $db->sql_escape($config_name) . "'";
+ $db->sql_query($sql);
+ }
+
+ //update setting in config table for mod enabled or not
+ set_config('mchat_enable', request_var('mchat_enable', 0));
+ // update setting in config table for allowing on index or not
+ set_config('mchat_on_index', request_var('mchat_on_index', 0));
+ // update setting in config table to allow new posts to display or not
+ set_config('mchat_new_posts', request_var('mchat_new_posts', 0));
+ // update setting in config table for stats on index
+ set_config('mchat_stats_index', request_var('mchat_stats_index', 0));
+ // and an entry into the log table
+ add_log('admin', 'LOG_MCHAT_CONFIG_UPDATE');
+
+ // purge the cache
+ $this->cache->destroy('_mchat_config');
+
+ // rebuild the cache
+ $this->functions_mchat->mchat_cache();
+
+ trigger_error($user->lang['MCHAT_CONFIG_SAVED'] . adm_back_link($this->u_action));
+ }
+ }
+
+ // let's get it on
+ $sql = 'SELECT * FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_CONFIG_TABLE;
+ $result = $db->sql_query($sql);
+ $mchat_config = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $mchat_config[$row['config_name']] = $row['config_value'];
+ }
+ $db->sql_freeresult($result);
+
+ $mchat_enable = isset($config['mchat_enable']) ? $config['mchat_enable'] : 0;
+ $mchat_on_index = isset($config['mchat_on_index']) ? $config['mchat_on_index'] : 0;
+ $mchat_version = isset($config['mchat_version']) ? $config['mchat_version'] : '';
+ $mchat_new_posts = isset($config['mchat_new_posts']) ? $config['mchat_new_posts'] : 0;
+ $mchat_stats_index = isset($config['mchat_stats_index']) ? $config['mchat_stats_index'] : 0;
+
+ $dateformat_options = '';
+ foreach ($user->lang['dateformats'] as $format => $null)
+ {
+ $dateformat_options .= '';
+ $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : '');
+ $dateformat_options .= ' ';
+ }
+
+ $s_custom = false;
+ $dateformat_options .= 'lang['dateformats'][$mchat_config['date']]))
+ {
+ $dateformat_options .= ' selected="selected"';
+ $s_custom = true;
+ }
+ $dateformat_options .= '>' . $user->lang['MCHAT_CUSTOM_DATEFORMAT'] . ' ';
+
+ $template->assign_vars(array(
+ 'MCHAT_ERROR' => isset($error) ? ((sizeof($error)) ? implode(' ', $error) : '') : '',
+ 'MCHAT_VERSION' => $mchat_version,
+ 'MCHAT_PRUNE' => !empty($mchat_row['prune_enable']) ? $mchat_row['prune_enable'] : $mchat_config['prune_enable'],
+ 'MCHAT_PRUNE_NUM' => !empty($mchat_row['prune_num']) ? $mchat_row['prune_num'] : $mchat_config['prune_num'],
+ 'MCHAT_ENABLE' => ($mchat_enable) ? true : false,
+ 'MCHAT_ON_INDEX' => ($mchat_on_index) ? true : false,
+ 'MCHAT_LOCATION' => !empty($mchat_row['location']) ? $mchat_row['location'] : $mchat_config['location'],
+ 'MCHAT_REFRESH' => !empty($mchat_row['refresh']) ? $mchat_row['refresh'] : $mchat_config['refresh'],
+ 'MCHAT_WHOIS_REFRESH' => !empty($mchat_row['whois_refresh']) ? $mchat_row['whois_refresh'] : $mchat_config['whois_refresh'],
+ 'MCHAT_MESSAGE_LIMIT' => !empty($mchat_row['message_limit']) ? $mchat_row['message_limit'] : $mchat_config['message_limit'],
+ 'MCHAT_MESSAGE_NUM' => !empty($mchat_row['message_num']) ? $mchat_row['message_num'] : $mchat_config['message_num'],
+ 'MCHAT_ARCHIVE_LIMIT' => !empty($mchat_row['archive_limit']) ? $mchat_row['archive_limit'] : $mchat_config['archive_limit'],
+ 'MCHAT_AVATARS' => !empty($mchat_row['avatars']) ? $mchat_row['avatars'] : $mchat_config['avatars'],
+ 'MCHAT_FLOOD_TIME' => !empty($mchat_row['flood_time']) ? $mchat_row['flood_time'] : $mchat_config['flood_time'],
+ 'MCHAT_MAX_MESSAGE_LNGTH' => !empty($mchat_row['max_message_lngth']) ? $mchat_row['max_message_lngth'] : $mchat_config['max_message_lngth'],
+ 'MCHAT_CUSTOM_PAGE' => !empty($mchat_row['custom_page']) ? $mchat_row['custom_page'] : $mchat_config['custom_page'],
+ 'MCHAT_DATE' => !empty($mchat_row['date']) ? $mchat_row['date'] : $mchat_config['date'],
+ 'MCHAT_DEFAULT_DATEFORMAT' => $config['default_dateformat'],
+ 'MCHAT_RULES' => !empty($mchat_row['rules']) ? $mchat_row['rules'] : $mchat_config['rules'],
+ 'MCHAT_WHOIS' => !empty($mchat_row['whois']) ? $mchat_row['whois'] : $mchat_config['whois'],
+ 'MCHAT_STATS_INDEX' => ($mchat_stats_index) ? true : false,
+ 'MCHAT_BBCODE_DISALLOWED' => !empty($mchat_row['bbcode_disallowed']) ? $mchat_row['bbcode_disallowed'] : $mchat_config['bbcode_disallowed'],
+ 'MCHAT_STATIC_MESSAGE' => !empty($mchat_row['static_message']) ? $mchat_row['static_message'] : $mchat_config['static_message'],
+ 'MCHAT_INDEX_HEIGHT' => !empty($mchat_row['index_height']) ? $mchat_row['index_height'] : $mchat_config['index_height'],
+ 'MCHAT_CUSTOM_HEIGHT' => !empty($mchat_row['custom_height']) ? $mchat_row['custom_height'] : $mchat_config['custom_height'],
+ 'MCHAT_OVERRIDE_SMILIE_LIMIT' => !empty($mchat_row['override_smilie_limit']) ? $mchat_row['override_smilie_limit'] : $mchat_config['override_smilie_limit'],
+ 'MCHAT_OVERRIDE_MIN_POST_CHARS' => !empty($mchat_row['override_min_post_chars']) ? $mchat_row['override_min_post_chars'] : $mchat_config['override_min_post_chars'],
+ 'MCHAT_TIMEOUT' => !empty($mchat_row['timeout']) ? $mchat_row['timeout'] : $mchat_config['timeout'],
+ 'MCHAT_NEW_POSTS' => ($mchat_new_posts) ? true : false,
+ 'MCHAT_PAUSE_ON_INPUT' => !empty($mchat_row['pause_on_input']) ? $mchat_row['pause_on_input'] : $mchat_config['pause_on_input'],
+
+ 'L_MCHAT_BBCODES_DISALLOWED_EXPLAIN' => sprintf($user->lang['MCHAT_BBCODES_DISALLOWED_EXPLAIN'], 'session_id) . '">', ' '),
+ 'L_MCHAT_TIMEOUT_EXPLAIN' => sprintf($user->lang['MCHAT_USER_TIMEOUT_EXPLAIN'],'session_id) . '">', ' ', $config['session_length']),
+
+ 'S_MCHAT_DATEFORMAT_OPTIONS' => $dateformat_options,
+ 'S_CUSTOM_DATEFORMAT' => $s_custom,
+
+ 'U_ACTION' => $this->u_action)
+ );
+
+ }
+}
\ No newline at end of file
diff --git a/adm/style/acp_mchat.html b/adm/style/acp_mchat.html
new file mode 100644
index 0000000..d249e07
--- /dev/null
+++ b/adm/style/acp_mchat.html
@@ -0,0 +1,179 @@
+
+
{L_MCHAT_TITLE}
+{L_MCHAT_VERSION} {MCHAT_VERSION}
+
+
+ {L_WARNING}
+
{MCHAT_ERROR}
+
+
+
+
+
\ No newline at end of file
diff --git a/adm/style/acp_users_mchat.html b/adm/style/acp_users_mchat.html
new file mode 100644
index 0000000..875d8cb
--- /dev/null
+++ b/adm/style/acp_users_mchat.html
@@ -0,0 +1,51 @@
+
+
+ {L_UCP_PROFILE_MCHAT}
+
+ {L_DISPLAY_MCHAT}{L_COLON}
+
+ id="mchat_index" checked="checked" /> {L_YES}
+ id="mchat_index" checked="checked" /> {L_NO}
+
+
+
+ {L_SOUND_MCHAT}{L_COLON}
+
+ id="mchat_sound" checked="checked" /> {L_YES}
+ id="mchat_sound" checked="checked" /> {L_NO}
+
+
+
+ {L_DISPLAY_STATS_INDEX}{L_COLON}
+
+ id="mchat_statsindex" checked="checked" /> {L_YES}
+ id="mchat_statsindex" checked="checked" /> {L_NO}
+
+
+
+ {L_DISPLAY_NEW_TOPICS}{L_COLON}
+
+ id="mchat_topics" checked="checked" /> {L_YES}
+ id="mchat_topics" checked="checked" /> {L_NO}
+
+
+
+ {L_DISPLAY_AVATARS}{L_COLON}
+
+ id="mchat_avatars" checked="checked" /> {L_YES}
+ id="mchat_avatars" checked="checked" /> {L_NO}
+
+
+
+ {L_CHAT_AREA}{L_COLON}
+
+ id="mchat_input_type" checked="checked" /> {L_INPUT_AREA}
+ id=""mchat_input_type" checked="checked" /> {L_TEXT_AREA}
+
+
+
+
+
+ {S_FORM_TOKEN}
+
+
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..c0a03d6
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,32 @@
+{
+ "name": "dmzx/mchat",
+ "type": "phpbb-extension",
+ "description": "mChat Extension for phpbb 3.1.x",
+ "homepage": "http://www.dmzx-web.net",
+ "version": "0.0.1",
+ "time": "2015-03-10",
+ "keywords": ["phpbb", "extension", "mchat"],
+ "license": "GPL-2.0",
+ "authors": [
+ {
+ "name": "dmzx",
+ "homepage": "http://www.dmzx-web.net",
+ "email": "info@dmzx-web.net",
+ "role": "Extension Developer"
+ },
+ {
+ "name": "Rich McGirr",
+ "homepage": "http://rmcgirr83.org",
+ "role": "Author"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "extra": {
+ "display-name": "mChat Extension",
+ "soft-require": {
+ "phpbb/phpbb": "3.1.*"
+ }
+ }
+}
\ No newline at end of file
diff --git a/config/routing.yml b/config/routing.yml
new file mode 100644
index 0000000..2a03a57
--- /dev/null
+++ b/config/routing.yml
@@ -0,0 +1,3 @@
+dmzx_mchat_controller:
+ path: /chat
+ defaults: { _controller: dmzx.mchat.controller:handle }
diff --git a/config/services.yml b/config/services.yml
new file mode 100644
index 0000000..404b9e5
--- /dev/null
+++ b/config/services.yml
@@ -0,0 +1,38 @@
+services:
+ dmzx.mchat.controller:
+ class: dmzx\mchat\controller\mchat
+ arguments:
+ - @dmzx.mchat.functions_mchat
+ - @config
+ - @controller.helper
+ - @template
+ - @user
+ - @auth
+ - @dbal.conn
+ - @cache
+ - @request
+ - %core.root_path%
+ - %core.php_ext%
+ - %core.table_prefix%
+ dmzx.mchat.functions_mchat:
+ class: dmzx\mchat\core\functions_mchat
+ arguments:
+ - @template
+ - @user
+ - @auth
+ - @dbal.conn
+ - @cache
+ - %core.table_prefix%
+ dmzx.mchat.listener:
+ class: dmzx\mchat\event\listener
+ arguments:
+ - @auth
+ - @config
+ - @template
+ - @user
+ - @dbal.conn
+ - @cache
+ - %core.root_path%
+ - %core.php_ext%
+ tags:
+ - { name: event.listener }
diff --git a/controller/mchat.php b/controller/mchat.php
new file mode 100644
index 0000000..51163c8
--- /dev/null
+++ b/controller/mchat.php
@@ -0,0 +1,1054 @@
+functions_mchat = $functions_mchat;
+ $this->config = $config;
+ $this->helper = $helper;
+ $this->template = $template;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->request = $request;
+
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->phpEx = $phpEx;
+ $this->table_prefix = $table_prefix;
+ }
+
+ /**
+ * Controller for mChat
+ *
+ * @return \Symfony\Component\HttpFoundation\Response A Symfony Response object
+ */
+ public function handle()
+ {
+ // Add lang file
+ //$this->user->add_lang(array('mods/mchat_lang', 'viewtopic', 'posting'));
+
+ //chat enabled
+ if (!$this->config['mchat_enable'])
+ {
+ $this->helper->error($this->user->lang['MCHAT_ENABLE'], E_USER_NOTICE);
+ }
+
+ // avatars
+ if (!function_exists('get_user_avatar'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_display.' . $this->phpEx);
+ }
+
+ if (($this->config_mchat = $this->cache->get('_mchat_config')) === false)
+ {
+ $this->functions_mchat->mchat_cache();
+ }
+ $this->config_mchat = $this->cache->get('_mchat_config');
+ // Access rights
+ $mchat_allow_bbcode = ($this->config['allow_bbcode'] && $this->auth->acl_get('u_mchat_bbcode')) ? true : false;
+ $mchat_smilies = ($this->config['allow_smilies'] && $this->auth->acl_get('u_mchat_smilies')) ? true : false;
+ $mchat_urls = ($this->config['allow_post_links'] && $this->auth->acl_get('u_mchat_urls')) ? true : false;
+ $mchat_ip = ($this->auth->acl_get('u_mchat_ip')) ? true : false;
+ $mchat_add_mess = ($this->auth->acl_get('u_mchat_use')) ? true : false;
+ $mchat_view = ($this->auth->acl_get('u_mchat_view')) ? true : false;
+ $mchat_no_flood = ($this->auth->acl_get('u_mchat_flood_ignore')) ? true : false;
+ $mchat_read_archive = ($this->auth->acl_get('u_mchat_archive')) ? true : false;
+ $mchat_founder = ($this->user->data['user_type'] == USER_FOUNDER) ? true : false;
+ $mchat_session_time = !empty($this->config_mchat['timeout']) ? $this->config_mchat['timeout'] : (!empty($this->config['load_online_time']) ? $this->config['load_online_time'] * 60 : $this->config['session_length']);
+ $mchat_rules = (!empty($this->config_mchat['rules']) || isset($this->user->lang[strtoupper('mchat_rules')])) ? true : false;
+ $mchat_avatars = (!empty($this->config_mchat['avatars']) && $this->user->optionget('viewavatars') && $this->user->data['user_mchat_avatars']) ? true : false;
+
+ // needed variables
+ // Request options.
+ $mchat_mode = request_var('mode', '');
+ $mchat_read_mode = $mchat_archive_mode = $mchat_custom_page = $mchat_no_message = false;
+ // set redirect if on index or custom page
+ $on_page = defined('MCHAT_INCLUDE') ? 'index' : 'mchat';
+
+
+ // grab fools..uhmmm, foes the user has
+ $foes_array = array();
+ $sql = 'SELECT * FROM ' . ZEBRA_TABLE . '
+ WHERE user_id = ' . $this->user->data['user_id'] . ' AND foe = 1';
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $foes_array[] = $row['zebra_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Request mode...
+ switch ($mchat_mode)
+ {
+ // rules popup..
+ case 'rules':
+ // If the rules are defined in the language file use them, else just use the entry in the database
+ if ($mchat_rules || isset($this->user->lang[strtoupper('mchat_rules')]))
+ {
+ if(isset($this->user->lang[strtoupper('mchat_rules')]))
+ {
+ $this->template->assign_var('MCHAT_RULES', $this->user->lang[strtoupper('mchat_rules')]);
+ }
+ else
+ {
+ $mchat_rules = $this->config_mchat['rules'];
+ $mchat_rules = explode("\n", $mchat_rules);
+
+ foreach ($mchat_rules as $mchat_rule)
+ {
+ $mchat_rule = htmlspecialchars($mchat_rule);
+ $this->template->assign_block_vars('rule', array(
+ 'MCHAT_RULE' => $mchat_rule,
+ ));
+ }
+ }
+
+ // Output the page
+ $this->helper->render('mchat_rules.html', $this->user->lang['MCHAT_HELP']);
+ }
+ else
+ {
+ // Show no rules
+ $this->helper->error('NO_MCHAT_RULES', E_USER_NOTICE);
+ }
+
+ break;
+ // whois function..
+ case 'whois':
+
+ // Must have auths
+ if ($mchat_mode == 'whois' && $mchat_ip)
+ {
+ // function already exists..
+ if (!function_exists('user_ipwhois'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->phpEx);
+ }
+
+ $this->user_ip = request_var('ip', '');
+
+ $this->template->assign_var('WHOIS', user_ipwhois($this->user_ip));
+
+ // Output the page
+ $this->helper->render('viewonline_whois.html', $this->user->lang['WHO_IS_ONLINE']);
+ }
+ else
+ {
+ // Show not authorized
+ $this->helper->error('NO_AUTH_OPERATION', E_USER_NOTICE);
+ }
+ break;
+ // Clean function...
+ case 'clean':
+
+ // User logged in?
+ if(!$this->user->data['is_registered'] || !$mchat_founder)
+ {
+ if(!$this->user->data['is_registered'])
+ {
+ // Login box...
+ login_box('', $this->user->lang['LOGIN']);
+ }
+ else if (!$mchat_founder)
+ {
+ // Show not authorized
+ $this->helper->error('NO_AUTH_OPERATION', E_USER_NOTICE);
+ }
+ }
+
+ $mchat_redirect = request_var('redirect', '');
+ $mchat_redirect = ($mchat_redirect == 'index') ? append_sid("{$this->phpbb_root_path}index.{$this->phpEx}") : $this->helper->route('dmzx_mchat_controller', array('#mChat'));
+
+ if(confirm_box(true))
+ {
+ // Run cleaner
+ $sql = 'TRUNCATE TABLE ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE;
+ $this->db->sql_query($sql);
+
+ meta_refresh(3, $mchat_redirect);
+ $this->helper->error($this->user->lang['MCHAT_CLEANED'].' '.sprintf($this->user->lang['RETURN_PAGE'], '', ' '), E_USER_NOTICE);
+ }
+ else
+ {
+ // Display confirm box
+ confirm_box(false, $this->user->lang['MCHAT_DELALLMESS']);
+ }
+ add_log('admin', 'LOG_MCHAT_TABLE_PRUNED');
+ redirect($mchat_redirect);
+ break;
+
+ // Archive function...
+ case 'archive':
+
+ if (!$mchat_read_archive || !$mchat_view)
+ {
+ // redirect to correct page
+ $mchat_redirect = append_sid("{$this->phpbb_root_path}index.{$this->phpEx}");
+ // Redirect to previous page
+ meta_refresh(3, $mchat_redirect);
+ $this->helper->error($this->user->lang['MCHAT_NOACCESS_ARCHIVE'].' '.sprintf($this->user->lang['RETURN_PAGE'], '', ' '), E_USER_NOTICE);
+ }
+
+ if ($this->config['mchat_enable'] && $mchat_read_archive && $mchat_view)
+ {
+ // how many chats do we have?
+ $sql = 'SELECT COUNT(message_id) AS messages FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE;
+ $result = $this->db->sql_query($sql);
+ $mchat_total_messages = $this->db->sql_fetchfield('messages');
+ $this->db->sql_freeresult($result);
+ // prune the chats if necessary and amount in ACP not empty
+ if ($this->config_mchat['prune_enable'] && ($mchat_total_messages > $this->config_mchat['prune_num'] && $this->config_mchat['prune_num'] > 0))
+ {
+ $this->functions_mchat->mchat_prune((int) $this->config_mchat['prune_num']);
+ }
+
+ // Reguest...
+ $mchat_archive_start = request_var('start', 0);
+ $sql_where = $this->user->data['user_mchat_topics'] ? '' : 'WHERE m.forum_id = 0';
+ // Message row
+ $sql = 'SELECT m.*, u.username, u.user_colour, u.user_avatar, u.user_avatar_type, u.user_avatar_width, u.user_avatar_height, u.user_allow_pm
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' m
+ LEFT JOIN ' . USERS_TABLE . ' u ON m.user_id = u.user_id
+ ' . $sql_where . '
+ ORDER BY m.message_id DESC';
+ $result = $this->db->sql_query_limit($sql, (int) $this->config_mchat['archive_limit'], $mchat_archive_start);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ foreach($rows as $row)
+ {
+ // auth check
+ if ($row['forum_id'] != 0 && !$this->auth->acl_get('f_read', $row['forum_id']))
+ {
+ continue;
+ }
+ // edit, delete and permission auths
+ $mchat_ban = ($this->auth->acl_get('a_authusers') && $this->user->data['user_id'] != $row['user_id']) ? true : false;
+ $mchat_edit = ($this->auth->acl_get('u_mchat_edit') && ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id'])) ? true : false;
+ $mchat_del = ($this->auth->acl_get('u_mchat_delete') && ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id'])) ? true : false;
+ $mchat_avatar = $row['user_avatar'] ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], ($row['user_avatar_width'] > $row['user_avatar_height']) ? 40 : (40 / $row['user_avatar_height']) * $row['user_avatar_width'], ($row['user_avatar_height'] > $row['user_avatar_width']) ? 40 : (40 / $row['user_avatar_width']) * $row['user_avatar_height']) : '';
+ $message_edit = $row['message'];
+ decode_message($message_edit, $row['bbcode_uid']);
+ $message_edit = str_replace('"', '"', $message_edit); // Edit Fix ;)
+ if (sizeof($foes_array))
+ {
+ if (in_array($row['user_id'], $foes_array))
+ {
+ $row['message'] = sprintf($this->user->lang['MCHAT_FOE'], get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']));
+ }
+ }
+ $row['username'] = mb_ereg_replace("'", "", $row['username']);
+ $this->template->assign_block_vars('mchatrow', array(
+ 'MCHAT_ALLOW_BAN' => $mchat_ban,
+ 'MCHAT_ALLOW_EDIT' => $mchat_edit,
+ 'MCHAT_ALLOW_DEL' => $mchat_del,
+ 'MCHAT_USER_AVATAR' => $mchat_avatar,
+ 'U_VIEWPROFILE' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$this->phpbb_root_path}memberlist.{$this->phpEx}", 'mode=viewprofile&u=' . $row['user_id']) : '',
+ 'U_USER_ID' => ($row['user_id'] != ANONYMOUS && $this->config['allow_privmsg'] && $this->auth->acl_get('u_sendpm') && $this->user->data['user_id'] != $row['user_id'] && $row['user_id'] != '55' && ($row['user_allow_pm'] || $this->auth->acl_gets('a_', 'm_') || $this->auth->acl_getf_global('m_'))) ? append_sid("{$this->phpbb_root_path}ucp.{$this->phpEx}", 'i=pm&mode=compose&u=' . $row['user_id']) : '',
+ 'MCHAT_MESSAGE_EDIT' => $message_edit,
+ 'MCHAT_MESSAGE_ID' => $row['message_id'],
+ 'MCHAT_USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USER_IP' => $row['user_ip'],
+ 'MCHAT_U_WHOIS' => $this->helper->route('dmzx_mchat_controller', array('mode=whois', 'ip=' . $row['user_ip'])),
+ 'MCHAT_U_BAN' => append_sid("{$this->phpbb_root_path}adm/index.{$this->phpEx}" ,'i=permissions&mode=setting_user_global&user_id[0]=' . $row['user_id'], true, $this->user->session_id),
+ 'MCHAT_MESSAGE' => generate_text_for_display($row['message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']),
+ 'MCHAT_TIME' => $this->user->format_date($row['message_time'], $this->config_mchat['date']),
+ 'MCHAT_CLASS' => ($row['message_id'] % 2) ? 1 : 2
+ ));
+ }
+
+ // Write no message
+ if (empty($rows))
+ {
+ $mchat_no_message = true;
+ }
+ }
+
+ // Run query again to get the total message rows...
+ $sql = 'SELECT COUNT(message_id) AS mess_id FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE;
+ $result = $this->db->sql_query($sql);
+ $mchat_total_message = $this->db->sql_fetchfield('mess_id');
+ $this->db->sql_freeresult($result);
+ // Page list function...
+ $this->template->assign_vars(array(
+ // 'MCHAT_PAGE_NUMBER' => $pagination->get_on_page($mchat_total_message, (int) $this->config_mchat['archive_limit'], $mchat_archive_start),
+ 'MCHAT_TOTAL_MESSAGES' => sprintf($this->user->lang['MCHAT_TOTALMESSAGES'], $mchat_total_message),
+ //\\ 'MCHAT_PAGINATION' => generate_pagination(append_sid("{$this->phpbb_root_path}mchat.{$this->phpEx}", 'mode=archive'), $mchat_total_message, (int) $this->config_mchat['archive_limit'], $mchat_archive_start, true)
+ ));
+
+ //add to navlinks
+ $this->template->assign_block_vars('navlinks', array(
+ 'FORUM_NAME' => $this->user->lang['MCHAT_ARCHIVE_PAGE'],
+ 'U_VIEW_FORUM' => $this->helper->route('dmzx_mchat_controller', array('mode=archive')))
+ );
+ // If archive mode request set true
+ $mchat_archive_mode = true;
+ $old_mode = 'archive';
+
+ break;
+
+ // Read function...
+ case 'read':
+
+ // If mChat disabled or user can't view the chat
+ if (!$this->config['mchat_enable'] || !$mchat_view)
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+ // if we're reading on the custom page, then we are chatting
+ if ($mchat_custom_page)
+ {
+ // insert user into the mChat sessions table
+ $this->functions_mchat->mchat_sessions($mchat_session_time, true);
+ }
+ // Request
+ $mchat_message_last_id = request_var('message_last_id', 0);
+ $sql_and = $this->user->data['user_mchat_topics'] ? '' : 'AND m.forum_id = 0';
+ $sql = 'SELECT m.*, u.username, u.user_colour, u.user_avatar, u.user_avatar_type, u.user_avatar_width, u.user_avatar_height, u.user_allow_pm
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' m, ' . USERS_TABLE . ' u
+ WHERE m.user_id = u.user_id
+ AND m.message_id > ' . (int) $mchat_message_last_id . '
+ ' . $sql_and . '
+ ORDER BY m.message_id DESC';
+ $result = $this->db->sql_query_limit($sql, (int) $this->config_mchat['message_limit']);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+ // Reverse the array wanting messages appear in reverse
+ $rows = array_reverse($rows);
+
+ foreach($rows as $row)
+ {
+ // auth check
+ if ($row['forum_id'] != 0 && !$this->auth->acl_get('f_read', $row['forum_id']))
+ {
+ continue;
+ }
+ // edit auths
+ if ($this->user->data['user_id'] == ANONYMOUS && $this->user->data['user_id'] == $row['user_id'])
+ {
+ $chat_auths = $this->user->data['session_ip'] == $row['user_ip'] ? true : false;
+ }
+ else
+ {
+ $chat_auths = $this->user->data['user_id'] == $row['user_id'] ? true : false;
+ }
+ // edit, delete and permission auths
+ $mchat_ban = ($this->auth->acl_get('a_authusers') && $this->user->data['user_id'] != $row['user_id']) ? true : false;
+ $mchat_edit = ($this->auth->acl_get('u_mchat_edit') && ($this->auth->acl_get('m_') || $chat_auths)) ? true : false;
+ $mchat_del = ($this->auth->acl_get('u_mchat_delete') && ($this->auth->acl_get('m_') || $chat_auths)) ? true : false;
+ $mchat_avatar = $row['user_avatar'] ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], ($row['user_avatar_width'] > $row['user_avatar_height']) ? 40 : (40 / $row['user_avatar_height']) * $row['user_avatar_width'], ($row['user_avatar_height'] > $row['user_avatar_width']) ? 40 : (40 / $row['user_avatar_width']) * $row['user_avatar_height']) : '';
+ $message_edit = $row['message'];
+ decode_message($message_edit, $row['bbcode_uid']);
+ $message_edit = str_replace('"', '"', $message_edit);
+ $message_edit = mb_ereg_replace("'", "", $message_edit); // Edit Fix ;)
+ if (sizeof($foes_array))
+ {
+ if (in_array($row['user_id'], $foes_array))
+ {
+ $row['message'] = sprintf($this->user->lang['MCHAT_FOE'], get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']));
+ }
+ }
+ $row['username'] = mb_ereg_replace("'", "", $row['username']);
+ $this->template->assign_block_vars('mchatrow', array(
+ 'MCHAT_ALLOW_BAN' => $mchat_ban,
+ 'MCHAT_ALLOW_EDIT' => $mchat_edit,
+ 'MCHAT_ALLOW_DEL' => $mchat_del,
+ 'MCHAT_USER_AVATAR' => $mchat_avatar,
+ 'U_VIEWPROFILE' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$this->phpbb_root_path}memberlist.{$this->phpEx}", 'mode=viewprofile&u=' . $row['user_id']) : '',
+ 'U_USER_ID' => ($row['user_id'] != ANONYMOUS && $this->config['allow_privmsg'] && $this->auth->acl_get('u_sendpm') && $this->user->data['user_id'] != $row['user_id'] && $row['user_id'] != '55' && ($row['user_allow_pm'] || $this->auth->acl_gets('a_', 'm_') || $this->auth->acl_getf_global('m_'))) ? append_sid("{$this->phpbb_root_path}ucp.{$this->phpEx}", 'i=pm&mode=compose&u=' . $row['user_id']) : '',
+ 'MCHAT_MESSAGE_EDIT' => $message_edit,
+ 'MCHAT_MESSAGE_ID' => $row['message_id'],
+ 'MCHAT_USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USER_IP' => $row['user_ip'],
+ 'MCHAT_U_WHOIS' => $this->helper->route('dmzx_mchat_controller', array('mode=whois', 'ip=' . $row['user_ip'])),
+ 'MCHAT_U_BAN' => append_sid("{$this->phpbb_root_path}adm/index.{$this->phpEx}" ,'i=permissions&mode=setting_user_global&user_id[0]=' . $row['user_id'], true, $this->user->session_id),
+ 'MCHAT_MESSAGE' => generate_text_for_display($row['message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']),
+ 'MCHAT_TIME' => $this->user->format_date($row['message_time'], $this->config_mchat['date']),
+ 'MCHAT_CLASS' => ($row['message_id'] % 2) ? 1 : 2
+ ));
+ }
+
+ // Write no message
+ if (empty($rows))
+ {
+ $mchat_no_message = true;
+ }
+
+ // If read mode request set true
+ $mchat_read_mode = true;
+
+ break;
+
+ // Stats function...
+ case 'stats':
+
+ // If mChat disabled or user can't view the chat
+ if (!$this->config['mchat_enable'] || !$mchat_view || !$this->config_mchat['whois'])
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+
+ $mchat_stats = $this->functions_mchat->mchat_users($mchat_session_time);
+
+ if(!empty($mchat_stats['online_userlist']))
+ {
+ $message = '';
+ }
+ else
+ {
+ $message = '' . $this->user->lang['MCHAT_NO_CHATTERS'] . ' (' . $mchat_stats['refresh_message'] . ')
';
+ }
+
+ if ($this->request->is_ajax())
+ {
+ return new \Symfony\Component\HttpFoundation\JsonResponse(
+ $message
+ );
+ }
+ else
+ {
+ throw new \phpbb\exception\http_exception(501, 'MCHAT_ERROR_NOT_IMPLEMENTED');
+ }
+
+ break;
+
+ // Add function...
+ case 'add':
+
+ // If mChat disabled
+ if (!$this->config['mchat_enable'] || !$mchat_add_mess || !check_form_key('mchat_posting', -1))
+ {
+ // Forbidden (for jQ AJAX request)
+ if ($this->request->is_ajax()) // FOR DEBUG
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+
+ // Reguest...
+ $message = utf8_normalize_nfc(request_var('message', '', true));
+
+ // must have something other than bbcode in the message
+ if (empty($mchatregex))
+ {
+ //let's strip all the bbcode
+ $mchatregex = '#\[/?[^\[\]]+\]#mi';
+ }
+ $message_chars = preg_replace($mchatregex, '', $message);
+ $message_chars = (utf8_strlen(trim($message_chars)) > 0) ? true : false;
+
+ if (!$message || !$message_chars)
+ {
+ // Not Implemented (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(501, 'MCHAT_ERROR_NOT_IMPLEMENTED');
+ }
+
+ // Flood control
+ if (!$mchat_no_flood && $this->config_mchat['flood_time'])
+ {
+ $mchat_flood_current_time = time();
+ $sql = 'SELECT message_time FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . '
+ WHERE user_id = ' . (int) $this->user->data['user_id'] . '
+ ORDER BY message_time DESC';
+ $result = $this->db->sql_query_limit($sql, 1);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ if($row['message_time'] > 0 && ($mchat_flood_current_time - $row['message_time']) < (int) $this->config_mchat['flood_time'])
+ {
+ // Locked (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(400, 'MCHAT_BAD_REQUEST');
+ }
+ }
+ // insert user into the mChat sessions table
+ $this->functions_mchat->mchat_sessions($mchat_session_time, true);
+ // we override the $this->config['min_post_chars'] entry?
+ if ($this->config_mchat['override_min_post_chars'])
+ {
+ $old_cfg['min_post_chars'] = $this->config['min_post_chars'];
+ $this->config['min_post_chars'] = 0;
+ }
+ //we do the same for the max number of smilies?
+ if ($this->config_mchat['override_smilie_limit'])
+ {
+ $old_cfg['max_post_smilies'] = $this->config['max_post_smilies'];
+ $this->config['max_post_smilies'] = 0;
+ }
+
+ // Add function part code from http://wiki.phpbb.com/Parsing_text
+ $uid = $bitfield = $options = ''; // will be modified by generate_text_for_storage
+ generate_text_for_storage($message, $uid, $bitfield, $options, $mchat_allow_bbcode, $mchat_urls, $mchat_smilies);
+ // Not allowed bbcodes
+ if (!$mchat_allow_bbcode || $this->config_mchat['bbcode_disallowed'])
+ {
+ if (!$mchat_allow_bbcode)
+ {
+ $bbcode_remove = '#\[/?[^\[\]]+\]#Usi';
+ $message = preg_replace($bbcode_remove, '', $message);
+ }
+ // disallowed bbcodes
+ else if ($this->config_mchat['bbcode_disallowed'])
+ {
+ if (empty($bbcode_replace))
+ {
+ $bbcode_replace = array('#\[(' . $this->config_mchat['bbcode_disallowed'] . ')[^\[\]]+\]#Usi',
+ '#\[/(' . $this->config_mchat['bbcode_disallowed'] . ')[^\[\]]+\]#Usi',
+ );
+ }
+ $message = preg_replace($bbcode_replace, '', $message);
+ }
+ }
+
+ $sql_ary = array(
+ 'forum_id' => 0,
+ 'post_id' => 0,
+ 'user_id' => $this->user->data['user_id'],
+ 'user_ip' => $this->user->data['session_ip'],
+ 'message' => str_replace('\'', '’', $message),
+ 'bbcode_bitfield' => $bitfield,
+ 'bbcode_uid' => $uid,
+ 'bbcode_options' => $options,
+ 'message_time' => time()
+ );
+ $sql = 'INSERT INTO ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+
+ // reset the config settings
+ if(isset($old_cfg['min_post_chars']))
+ {
+ $this->config['min_post_chars'] = $old_cfg['min_post_chars'];
+ unset($old_cfg['min_post_chars']);
+ }
+ if(isset($old_cfg['max_post_smilies']))
+ {
+ $this->config['max_post_smilies'] = $old_cfg['max_post_smilies'];
+ unset($old_cfg['max_post_smilies']);
+ }
+
+ // Stop run code!
+ if ($this->request->is_ajax())
+ {
+ return new \Symfony\Component\HttpFoundation\JsonResponse(array(
+ 'success' => true,
+ ));
+ }
+ else
+ {
+ exit_handler();
+ }
+ break;
+
+ // Edit function...
+ case 'edit':
+
+ $message_id = request_var('message_id', 0);
+
+ // If mChat disabled and not edit
+ if (!$this->config['mchat_enable'] || !$message_id)
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+
+ // check for the correct user
+ $sql = 'SELECT *
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . '
+ WHERE message_id = ' . (int) $message_id;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ // edit and delete auths
+ $mchat_edit = $this->auth->acl_get('u_mchat_edit')&& ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id']) ? true : false;
+ $mchat_del = $this->auth->acl_get('u_mchat_delete') && ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id']) ? true : false;
+ // If mChat disabled and not edit
+ if (!$mchat_edit)
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+ // Reguest...
+ $message = request_var('message', '', true);
+
+ // must have something other than bbcode in the message
+ if (empty($mchatregex))
+ {
+ //let's strip all the bbcode
+ $mchatregex = '#\[/?[^\[\]]+\]#mi';
+ }
+ $message_chars = preg_replace($mchatregex, '', $message);
+ $message_chars = (utf8_strlen(trim($message_chars)) > 0) ? true : false;
+ if (!$message || !$message_chars)
+ {
+ // Not Implemented (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(501, 'MCHAT_ERROR_NOT_IMPLEMENTED');
+ }
+
+ // Message limit
+ $message = ($this->config_mchat['max_message_lngth'] != 0 && utf8_strlen($message) >= $this->config_mchat['max_message_lngth'] + 3) ? utf8_substr($message, 0, $this->config_mchat['max_message_lngth']).'...' : $message;
+
+ // we override the $this->config['min_post_chars'] entry?
+ if ($this->config_mchat['override_min_post_chars'])
+ {
+ $old_cfg['min_post_chars'] = $this->config['min_post_chars'];
+ $this->config['min_post_chars'] = 0;
+ }
+ //we do the same for the max number of smilies?
+ if ($this->config_mchat['override_smilie_limit'])
+ {
+ $old_cfg['max_post_smilies'] = $this->config['max_post_smilies'];
+ $this->config['max_post_smilies'] = 0;
+ }
+
+ // Edit function part code from http://wiki.phpbb.com/Parsing_text
+ $uid = $bitfield = $options = ''; // will be modified by generate_text_for_storage
+ generate_text_for_storage($message, $uid, $bitfield, $options, $mchat_allow_bbcode, $mchat_urls, $mchat_smilies);
+
+ // Not allowed bbcodes
+ if (!$mchat_allow_bbcode || $this->config_mchat['bbcode_disallowed'])
+ {
+ if (!$mchat_allow_bbcode)
+ {
+ $bbcode_remove = '#\[/?[^\[\]]+\]#Usi';
+ $message = preg_replace($bbcode_remove, '', $message);
+ }
+ // disallowed bbcodes
+ else if ($this->config_mchat['bbcode_disallowed'])
+ {
+ if (empty($bbcode_replace))
+ {
+ $bbcode_replace = array('#\[(' . $this->config_mchat['bbcode_disallowed'] . ')[^\[\]]+\]#Usi',
+ '#\[/(' . $this->config_mchat['bbcode_disallowed'] . ')[^\[\]]+\]#Usi',
+ );
+ }
+ $message = preg_replace($bbcode_replace, '', $message);
+ }
+ }
+
+ $sql_ary = array(
+ 'message' => str_replace('\'', '’', $message),
+ 'bbcode_bitfield' => $bitfield,
+ 'bbcode_uid' => $uid,
+ 'bbcode_options' => $options
+ );
+
+ $sql = 'UPDATE ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary).'
+ WHERE message_id = ' . (int) $message_id;
+ $this->db->sql_query($sql);
+
+ // Message edited...now read it
+ $sql = 'SELECT m.*, u.username, u.user_colour, u.user_avatar, u.user_avatar_type, u.user_avatar_width, u.user_avatar_height, u.user_allow_pm
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' m, ' . USERS_TABLE . ' u
+ WHERE m.user_id = u.user_id
+ AND m.message_id = ' . (int) $message_id . '
+ ORDER BY m.message_id DESC';
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ $message_edit = $row['message'];
+
+ decode_message($message_edit, $row['bbcode_uid']);
+ $message_edit = str_replace('"', '"', $message_edit); // Edit Fix ;)
+ $message_edit = mb_ereg_replace("'", "", $message_edit); // Edit Fix ;)
+ $mchat_ban = ($this->auth->acl_get('a_authusers') && $this->user->data['user_id'] != $row['user_id']) ? true : false;
+ $mchat_avatar = $row['user_avatar'] ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], ($row['user_avatar_width'] > $row['user_avatar_height']) ? 40 : (40 / $row['user_avatar_height']) * $row['user_avatar_width'], ($row['user_avatar_height'] > $row['user_avatar_width']) ? 40 : (40 / $row['user_avatar_width']) * $row['user_avatar_height']) : '';
+ $this->template->assign_block_vars('mchatrow', array(
+ 'MCHAT_ALLOW_BAN' => $mchat_ban,
+ 'MCHAT_ALLOW_EDIT' => $mchat_edit,
+ 'MCHAT_ALLOW_DEL' => $mchat_del,
+ 'MCHAT_MESSAGE_EDIT' => $message_edit,
+ 'MCHAT_USER_AVATAR' => $mchat_avatar,
+ 'U_VIEWPROFILE' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$this->phpbb_root_path}memberlist.{$this->phpEx}", 'mode=viewprofile&u=' . $row['user_id']) : '',
+ 'U_USER_ID' => ($row['user_id'] != ANONYMOUS && $this->config['allow_privmsg'] && $this->auth->acl_get('u_sendpm') && $this->user->data['user_id'] != $row['user_id'] && $row['user_id'] != '55' && ($row['user_allow_pm'] || $this->auth->acl_gets('a_', 'm_') || $this->auth->acl_getf_global('m_'))) ? append_sid("{$this->phpbb_root_path}ucp.{$this->phpEx}", 'i=pm&mode=compose&u=' . $row['user_id']) : '',
+ 'MCHAT_MESSAGE_ID' => $row['message_id'],
+ 'MCHAT_USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USER_IP' => $row['user_ip'],
+ 'MCHAT_U_WHOIS' => $this->helper->route('dmzx_mchat_controller', array('mode=whois', 'ip=' . $row['user_ip'])),
+ 'MCHAT_U_BAN' => append_sid("{$this->phpbb_root_path}adm/index.{$this->phpEx}" ,'i=permissions&mode=setting_user_global&user_id[0]=' . $row['user_id'], true, $this->user->session_id),
+ 'MCHAT_MESSAGE' => censor_text(generate_text_for_display($row['message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options'])),
+ 'MCHAT_TIME' => $this->user->format_date($row['message_time'], $this->config_mchat['date']),
+ 'MCHAT_CLASS' => ($row['message_id'] % 2) ? 1 : 2
+ ));
+ // reset the config settings
+ if(isset($old_cfg['min_post_chars']))
+ {
+ $this->config['min_post_chars'] = $old_cfg['min_post_chars'];
+ unset($old_cfg['min_post_chars']);
+ }
+ if(isset($old_cfg['max_post_smilies']))
+ {
+ $this->config['max_post_smilies'] = $old_cfg['max_post_smilies'];
+ unset($old_cfg['max_post_smilies']);
+ }
+ //adds a log
+ $message_author = get_username_string('no_profile', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']);
+ add_log('admin', 'LOG_EDITED_MCHAT', $message_author);
+ // insert user into the mChat sessions table
+ $this->functions_mchat->mchat_sessions($mchat_session_time, true);
+ // If read mode request set true
+ $mchat_read_mode = true;
+
+ break;
+
+ // Delete function...
+ case 'delete':
+
+ $message_id = request_var('message_id', 0);
+ // If mChat disabled
+ if (!$this->config['mchat_enable'] || !$message_id)
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+ // check for the correct user
+ $sql = 'SELECT m.*, u.username, u.user_colour
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' m
+ LEFT JOIN ' . USERS_TABLE . ' u ON m.user_id = u.user_id
+ WHERE m.message_id = ' . (int) $message_id;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+ // edit and delete auths
+ $mchat_edit = $this->auth->acl_get('u_mchat_edit')&& ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id']) ? true : false;
+ $mchat_del = $this->auth->acl_get('u_mchat_delete') && ($this->auth->acl_get('m_') || $this->user->data['user_id'] == $row['user_id']) ? true : false;
+
+ // If mChat disabled
+ if (!$mchat_del)
+ {
+ // Forbidden (for jQ AJAX request)
+ throw new \phpbb\exception\http_exception(403, 'MCHAT_ERROR_FORBIDDEN');
+ }
+
+ // Run delete!
+ $sql = 'DELETE FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . '
+ WHERE message_id = ' . (int) $message_id;
+ $this->db->sql_query($sql);
+ //adds a log
+ $message_author = get_username_string('no_profile', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']);
+ add_log('admin', 'LOG_DELETED_MCHAT', $message_author);
+ // insert user into the mChat sessions table
+ $this->functions_mchat->mchat_sessions($mchat_session_time, true);
+
+ // Stop running code
+ if ($this->request->is_ajax())
+ {
+ return new \Symfony\Component\HttpFoundation\JsonResponse(array(
+ 'success' => true,
+ ));
+ }
+ else
+ {
+ exit_handler();
+ }
+ break;
+
+ // Default function...
+ default:
+
+ // TODO: We are assuming there is no include on index at first
+ $mchat_include_index = false;
+
+ // If not include in index.php set mchat.php page true
+ if (!$mchat_include_index)
+ {
+ // Yes its custom page...
+ $mchat_custom_page = true;
+
+ // If custom page false mchat.php page redirect to index...
+ if (!$this->config_mchat['custom_page'] && $mchat_custom_page)
+ {
+ $mchat_redirect = append_sid("{$this->phpbb_root_path}index.{$this->phpEx}");
+ // Redirect to previous page
+ meta_refresh(3, $mchat_redirect);
+ $this->helper->error($this->user->lang['MCHAT_NO_CUSTOM_PAGE'].' '.sprintf($this->user->lang['RETURN_PAGE'], '', ' '), E_USER_NOTICE);
+ }
+
+ // user has permissions to view the custom chat?
+ if (!$mchat_view && $mchat_custom_page)
+ {
+ $this->helper->error($this->user->lang['NOT_AUTHORISED'], E_USER_NOTICE);
+ }
+
+ // if whois true
+ if ($this->config_mchat['whois'])
+ {
+ // Grab group details for legend display for who is online on the custom page.
+ if ($this->auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel'))
+ {
+ $sql = 'SELECT group_id, group_name, group_colour, group_type FROM ' . GROUPS_TABLE . '
+ WHERE group_legend = 1
+ ORDER BY group_name ASC';
+ }
+ else
+ {
+ $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type FROM ' . GROUPS_TABLE . ' g
+ LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (g.group_id = ug.group_id AND ug.user_id = ' . $this->user->data['user_id'] . ' AND ug.user_pending = 0)
+ WHERE g.group_legend = 1
+ AND (g.group_type <> ' . GROUP_HIDDEN . '
+ OR ug.user_id = ' . (int) $this->user->data['user_id'] . ')
+ ORDER BY g.group_name ASC';
+ }
+ $result = $this->db->sql_query($sql);
+ $legend = array();
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $colour_text = ($row['group_colour']) ? ' style="color:#'.$row['group_colour'].'"' : '';
+ $group_name = ($row['group_type'] == GROUP_SPECIAL) ? $this->user->lang['G_'.$row['group_name']] : $row['group_name'];
+ if ($row['group_name'] == 'BOTS' || ($this->user->data['user_id'] != ANONYMOUS && !$this->auth->acl_get('u_viewprofile')))
+ {
+ $legend[] = ''.$group_name.' ';
+ }
+ else
+ {
+ $legend[] = 'phpbb_root_path}memberlist.{$this->phpEx}", 'mode=group&g='.$row['group_id']).'">'.$group_name.' ';
+ }
+ }
+ $this->db->sql_freeresult($result);
+ $legend = implode(', ', $legend);
+
+ // Assign index specific vars
+ $this->template->assign_vars(array(
+ 'LEGEND' => $legend,
+ ));
+ }
+ $this->template->assign_block_vars('navlinks', array(
+ 'FORUM_NAME' => $this->user->lang['MCHAT_TITLE'],
+ 'U_VIEW_FORUM' => $this->helper->route('dmzx_mchat_controller'),
+ ));
+ }
+
+ // Run code...
+ if ($mchat_view)
+ {
+ $message_number = $mchat_custom_page ? $this->config_mchat['message_limit'] : $this->config_mchat['message_num'];
+ $sql_where = $this->user->data['user_mchat_topics'] ? '' : 'WHERE m.forum_id = 0';
+ // Message row
+ $sql = 'SELECT m.*, u.username, u.user_colour, u.user_avatar, u.user_avatar_type, u.user_avatar_width, u.user_avatar_height, u.user_allow_pm
+ FROM ' . $this->table_prefix . \dmzx\mchat\core\functions_mchat::MCHAT_TABLE . ' m
+ LEFT JOIN ' . USERS_TABLE . ' u ON m.user_id = u.user_id
+ ' . $sql_where . '
+ ORDER BY message_id DESC';
+ $result = $this->db->sql_query_limit($sql, $message_number);
+ $rows = $this->db->sql_fetchrowset($result);
+ $this->db->sql_freeresult($result);
+
+ $rows = array_reverse($rows, true);
+
+ foreach($rows as $row)
+ {
+ // auth check
+ if ($row['forum_id'] != 0 && !$this->auth->acl_get('f_read', $row['forum_id']))
+ {
+ continue;
+ }
+ // edit, delete and permission auths
+ $mchat_ban = ($this->auth->acl_get('a_authusers') && $this->user->data['user_id'] != $row['user_id']) ? true : false;
+ // edit auths
+ if ($this->user->data['user_id'] == ANONYMOUS && $this->user->data['user_id'] == $row['user_id'])
+ {
+ $chat_auths = $this->user->data['session_ip'] == $row['user_ip'] ? true : false;
+ }
+ else
+ {
+ $chat_auths = $this->user->data['user_id'] == $row['user_id'] ? true : false;
+ }
+ $mchat_edit = ($this->auth->acl_get('u_mchat_edit') && ($this->auth->acl_get('m_') || $chat_auths)) ? true : false;
+ $mchat_del = ($this->auth->acl_get('u_mchat_delete') && ($this->auth->acl_get('m_') || $chat_auths)) ? true : false;
+ $mchat_avatar = $row['user_avatar'] ? get_user_avatar($row['user_avatar'], $row['user_avatar_type'], ($row['user_avatar_width'] > $row['user_avatar_height']) ? 40 : (40 / $row['user_avatar_height']) * $row['user_avatar_width'], ($row['user_avatar_height'] > $row['user_avatar_width']) ? 40 : (40 / $row['user_avatar_width']) * $row['user_avatar_height']) : '';
+ $message_edit = $row['message'];
+ decode_message($message_edit, $row['bbcode_uid']);
+ $message_edit = str_replace('"', '"', $message_edit); // Edit Fix ;)
+ $message_edit = mb_ereg_replace("'", "", $message_edit);
+ if (sizeof($foes_array))
+ {
+ if (in_array($row['user_id'], $foes_array))
+ {
+ $row['message'] = sprintf($this->user->lang['MCHAT_FOE'], get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']));
+ }
+ }
+ $row['username'] = mb_ereg_replace("'", "", $row['username']);
+ $message = str_replace('\'', '’', $row['message']);
+ $this->template->assign_block_vars('mchatrow', array(
+ 'MCHAT_ALLOW_BAN' => $mchat_ban,
+ 'MCHAT_ALLOW_EDIT' => $mchat_edit,
+ 'MCHAT_ALLOW_DEL' => $mchat_del,
+ 'MCHAT_USER_AVATAR' => $mchat_avatar,
+ 'U_VIEWPROFILE' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$this->phpbb_root_path}memberlist.{$this->phpEx}", 'mode=viewprofile&u=' . $row['user_id']) : '',
+ 'U_USER_ID' => ($row['user_id'] != ANONYMOUS && $this->config['allow_privmsg'] && $this->auth->acl_get('u_sendpm') && $this->user->data['user_id'] != $row['user_id'] && $row['user_id'] != '55' && ($row['user_allow_pm'] || $this->auth->acl_gets('a_', 'm_') || $this->auth->acl_getf_global('m_'))) ? append_sid("{$this->phpbb_root_path}ucp.{$this->phpEx}", 'i=pm&mode=compose&u=' . $row['user_id']) : '',
+ 'MCHAT_MESSAGE_EDIT' => $message_edit,
+ 'MCHAT_MESSAGE_ID' => $row['message_id'],
+ 'MCHAT_USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USERNAME_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']),
+ 'MCHAT_USER_IP' => $row['user_ip'],
+ 'MCHAT_U_WHOIS' => $this->helper->route('dmzx_mchat_controller', array('mode=whois', 'ip=' . $row['user_ip'])),
+ 'MCHAT_U_BAN' => append_sid("{$this->phpbb_root_path}adm/index.{$this->phpEx}" ,'i=permissions&mode=setting_user_global&user_id[0]=' . $row['user_id'], true, $this->user->session_id),
+ 'MCHAT_MESSAGE' => generate_text_for_display($message, $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']),
+ 'MCHAT_TIME' => $this->user->format_date($row['message_time'], $this->config_mchat['date']),
+ 'MCHAT_CLASS' => ($row['message_id'] % 2) ? 1 : 2
+ ));
+
+ }
+
+ // Write no message
+ if (empty($rows))
+ {
+ $mchat_no_message = true;
+ }
+ // display custom bbcodes
+ if($mchat_allow_bbcode && $this->config['allow_bbcode'])
+ {
+ $this->functions_mchat->display_mchat_bbcodes();
+ }
+ // Smile row
+ if ($mchat_smilies)
+ {
+ if (!function_exists('generate_smilies'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_posting.' . $this->phpEx);
+ }
+ generate_smilies('inline', 0);
+ }
+ // If the static message is defined in the language file use it, else just use the entry in the database
+ if (isset($this->user->lang[strtoupper('static_message')]) || !empty($this->config_mchat['static_message']))
+ {
+ $this->config_mchat['static_message'] = $this->config_mchat['static_message'];
+ if(isset($this->user->lang[strtoupper('static_message')]))
+ {
+ $this->config_mchat['static_message'] = $this->user->lang[strtoupper('static_message')];
+ }
+ }
+ // If the static message is defined in the language file use it, else just use the entry in the database
+ if (isset($this->user->lang[strtoupper('mchat_rules')]) || !empty($this->config_mchat['rules']))
+ {
+ if(isset($this->user->lang[strtoupper('mchat_rules')]))
+ {
+ $this->config_mchat['rules'] = $this->user->lang[strtoupper('mchat_rules')];
+ }
+ }
+ // a list of users using the chat
+ if ($mchat_custom_page)
+ {
+ $mchat_users = $this->functions_mchat->mchat_users($mchat_session_time, true);
+ }
+ else
+ {
+ $mchat_users = $this->functions_mchat->mchat_users($mchat_session_time);
+ }
+ $this->template->assign_vars(array(
+ 'MCHAT_USERS_COUNT' => $mchat_users['mchat_users_count'],
+ 'MCHAT_USERS_LIST' => $mchat_users['online_userlist'],
+ ));
+ }
+ break;
+ }
+ $copyright = base64_decode('PGEgaHJlZj0iaHR0cDovL3JtY2dpcnI4My5vcmciPlJNY0dpcnI4MzwvYT4gJmNvcHk7IDxhIGhyZWY9Imh0dHA6Ly93d3cuZG16eC13ZWIubmV0IiB0aXRsZT0id3d3LmRtengtd2ViLm5ldCI+ZG16eDwvYT4=');
+ add_form_key('mchat_posting');
+ // Template function...
+ $this->template->assign_vars(array(
+ 'MCHAT_FILE_NAME' => $this->helper->route('dmzx_mchat_controller'),
+ 'MCHAT_REFRESH_JS' => 1000 * $this->config_mchat['refresh'],
+ 'MCHAT_ADD_MESSAGE' => $mchat_add_mess,
+ 'MCHAT_READ_MODE' => $mchat_read_mode,
+ 'MCHAT_ARCHIVE_MODE' => $mchat_archive_mode,
+ 'MCHAT_INPUT_TYPE' => $this->user->data['user_mchat_input_area'],
+ 'MCHAT_RULES' => $mchat_rules,
+ 'MCHAT_ALLOW_SMILES' => $mchat_smilies,
+ 'MCHAT_ALLOW_IP' => $mchat_ip,
+ 'MCHAT_NOMESSAGE_MODE' => $mchat_no_message,
+ 'MCHAT_ALLOW_BBCODES' => ($mchat_allow_bbcode && $this->config['allow_bbcode']) ? true : false,
+ 'MCHAT_ENABLE' => $this->config['mchat_enable'],
+ 'MCHAT_ARCHIVE_URL' => $this->helper->route('dmzx_mchat_controller', array('mode=archive')),
+ 'MCHAT_CUSTOM_PAGE' => $mchat_custom_page,
+ 'MCHAT_INDEX_HEIGHT' => $this->config_mchat['index_height'],
+ 'MCHAT_CUSTOM_HEIGHT' => $this->config_mchat['custom_height'],
+ 'MCHAT_READ_ARCHIVE_BUTTON' => $mchat_read_archive,
+ 'MCHAT_FOUNDER' => $mchat_founder,
+ 'MCHAT_CLEAN_URL' => $this->helper->route('dmzx_mchat_controller', array('mode=clean', 'redirect=' . $on_page)),
+ 'MCHAT_STATIC_MESS' => !empty($this->config_mchat['static_message']) ? htmlspecialchars_decode($this->config_mchat['static_message']) : '',
+ 'L_MCHAT_COPYRIGHT' => $copyright,
+ 'MCHAT_WHOIS' => $this->config_mchat['whois'],
+ 'MCHAT_MESSAGE_LNGTH' => $this->config_mchat['max_message_lngth'],
+ 'L_MCHAT_MESSAGE_LNGTH_EXPLAIN' => (intval($this->config_mchat['max_message_lngth'])) ? sprintf($this->user->lang['MCHAT_MESSAGE_LNGTH_EXPLAIN'], intval($this->config_mchat['max_message_lngth'])) : '',
+ 'MCHAT_MESS_LONG' => sprintf($this->user->lang['MCHAT_MESS_LONG'], $this->config_mchat['max_message_lngth']),
+ 'MCHAT_USER_TIMEOUT' => $this->config_mchat['timeout'] ? 1000 * $this->config_mchat['timeout'] : false,
+ 'MCHAT_WHOIS_REFRESH' => 1000 * $this->config_mchat['whois_refresh'],
+ 'MCHAT_PAUSE_ON_INPUT' => $this->config_mchat['pause_on_input'] ? true : false,
+ 'L_MCHAT_ONLINE_EXPLAIN' => $this->functions_mchat->mchat_session_time($mchat_session_time),
+ 'MCHAT_REFRESH_YES' => sprintf($this->user->lang['MCHAT_REFRESH_YES'], $this->config_mchat['refresh']),
+ 'L_MCHAT_WHOIS_REFRESH_EXPLAIN' => sprintf($this->user->lang['WHO_IS_REFRESH_EXPLAIN'], $this->config_mchat['whois_refresh']),
+ 'S_MCHAT_AVATARS' => $mchat_avatars,
+ 'S_MCHAT_LOCATION' => $this->config_mchat['location'],
+ 'S_MCHAT_SOUND_YES' => $this->user->data['user_mchat_sound'],
+ 'S_MCHAT_INDEX_STATS' => $this->user->data['user_mchat_stats_index'],
+ 'U_MORE_SMILIES' => append_sid("{$this->phpbb_root_path}posting.{$this->phpEx}", 'mode=smilies'),
+ 'U_MCHAT_RULES' => $this->helper->route('dmzx_mchat_controller', array('mode=rules')),
+ ));
+
+ return $this->helper->render('mchat_body.html', $this->user->lang['MCHAT_TITLE']);
+ }
+}
diff --git a/core/functions_mchat.php b/core/functions_mchat.php
new file mode 100644
index 0000000..15816cc
--- /dev/null
+++ b/core/functions_mchat.php
@@ -0,0 +1,374 @@
+template = $template;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->db = $db;
+ $this->cache = $cache;
+
+ $this->table_prefix = $table_prefix;
+ }
+
+ // mchat_cache
+ /**
+ * builds the cache if it doesn't exist
+ */
+ function mchat_cache()
+ {
+ // Grab the config entries in teh ACP...and cache em :P
+ if (($config_mchat = $this->cache->get('_mchat_config')) === false)
+ {
+ $sql = 'SELECT * FROM ' . $this->table_prefix . self::MCHAT_CONFIG_TABLE;
+ $result = $this->db->sql_query($sql);
+ $config_mchat = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $config_mchat[$row['config_name']] = $row['config_value'];
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_mchat_config', $config_mchat);
+ }
+ }
+
+ // mchat_user_fix
+ /**
+ * @param $user_id the id of the user being deleted from the forum
+ *
+ */
+ function mchat_user_fix($user_id)
+ {
+ $sql = 'UPDATE ' . $this->table_prefix . self::MCHAT_TABLE . '
+ SET user_id = ' . ANONYMOUS . '
+ WHERE user_id = ' . (int) $user_id;
+ $this->db->sql_query($sql);
+
+ return;
+ }
+
+ // mchat_session_time
+ /**
+ * @param $time the amount of time to display
+ *
+ */
+ function mchat_session_time($time)
+ {
+ // fix the display of the time limit
+ // hours, minutes, seconds
+ $chat_session = '';
+ $chat_timeout = (int) $time;
+ $hours = $minutes = $seconds = 0;
+
+ if ($chat_timeout >= 3600)
+ {
+ $hours = floor($chat_timeout / 3600);
+ $chat_timeout = $chat_timeout - ($hours * 3600);
+ $chat_session .= $hours > 1 ? ($hours . ' ' . $this->user->lang['MCHAT_HOURS']) : ($hours . ' ' . $this->user->lang['MCHAT_HOUR']);
+ }
+ $minutes = floor($chat_timeout / 60);
+ if ($minutes)
+ {
+ $minutes = $minutes > 1 ? ($minutes . ' ' . $this->user->lang['MCHAT_MINUTES']) : ($minutes . ' ' . $this->user->lang['MCHAT_MINUTE']);
+ $chat_timeout = $chat_timeout - ($minutes * 60);
+ $chat_session .= $minutes;
+ }
+ $seconds = ceil($chat_timeout);
+ if ($seconds)
+ {
+ $seconds = $seconds > 1 ? ($seconds . ' ' . $this->user->lang['MCHAT_SECONDS']) : ($seconds . ' ' . $this->user->lang['MCHAT_SECOND']);
+ $chat_session .= $seconds;
+ }
+ return sprintf($this->user->lang['MCHAT_ONLINE_EXPLAIN'], $chat_session);
+ }
+
+ // mchat_users
+ /**
+ * @param $session_time amount of time before a users session times out
+ */
+ function mchat_users($session_time, $on_page = false)
+ {
+ $check_time = time() - (int) $session_time;
+
+ $sql = 'DELETE FROM ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' WHERE user_lastupdate < ' . $check_time;
+ $this->db->sql_query($sql);
+
+ // add the user into the sessions upon first visit
+ if($on_page && ($this->user->data['user_id'] != ANONYMOUS && !$this->user->data['is_bot']))
+ {
+ $this->mchat_sessions($session_time);
+ }
+
+ $mchat_user_count = 0;
+ $mchat_user_list = '';
+
+ $sql = 'SELECT m.user_id, u.username, u.user_type, u.user_allow_viewonline, u.user_colour
+ FROM ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' m
+ LEFT JOIN ' . USERS_TABLE . ' u ON m.user_id = u.user_id
+ WHERE m.user_lastupdate > ' . $check_time . '
+ ORDER BY u.username ASC';
+ $result = $this->db->sql_query($sql);
+ $can_view_hidden = $this->auth->acl_get('u_viewonline');
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!$row['user_allow_viewonline'])
+ {
+ if (!$can_view_hidden)
+ {
+ continue;
+ }
+ else
+ {
+ $row['username'] = '' . $row['username'] . ' ';
+ }
+ }
+ $mchat_user_count++;
+ $mchat_user_online_link = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->user->lang['GUEST']);
+ $mchat_user_list .= ($mchat_user_list != '') ? $this->user->lang['COMMA_SEPARATOR'] . $mchat_user_online_link : $mchat_user_online_link;
+ }
+ $this->db->sql_freeresult($result);
+
+ $refresh_message = $this->mchat_session_time($session_time);
+ if (!$mchat_user_count)
+ {
+ return array(
+ 'online_userlist' => '',
+ 'mchat_users_count' => $this->user->lang['MCHAT_NO_CHATTERS'],
+ 'refresh_message' => $refresh_message,
+ );
+ }
+ else
+ {
+ return array(
+ 'online_userlist' => $mchat_user_list,
+ 'mchat_users_count' => $mchat_user_count > 1 ? sprintf($this->user->lang['MCHAT_ONLINE_USERS_TOTAL'], $mchat_user_count) : sprintf($this->user->lang['MCHAT_ONLINE_USER_TOTAL'], $mchat_user_count),
+ 'refresh_message' => $refresh_message,
+ );
+ }
+ }
+
+ // mchat_sessions
+ /**
+ * @param mixed $session_time amount of time before a user is not shown as being in the chat
+ */
+ function mchat_sessions($session_time)
+ {
+ $check_time = time() - (int) $session_time;
+ $sql = 'DELETE FROM ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' WHERE user_lastupdate <' . $check_time;
+ $this->db->sql_query($sql);
+
+ // insert user into the mChat sessions table
+ if ($this->user->data['user_type'] == USER_FOUNDER || $this->user->data['user_type'] == USER_NORMAL)
+ {
+ $sql = 'SELECT * FROM ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' WHERE user_id =' . (int) $this->user->data['user_id'];
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ $sql_ary = array(
+ 'user_id' => $this->user->data['user_id'],
+ 'user_lastupdate' => time(),
+ );
+ $sql = 'INSERT INTO ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
+ $this->db->sql_query($sql);
+ }
+ else
+ {
+ $sql_ary = array(
+ 'user_lastupdate' => time(),
+ );
+ $sql = 'UPDATE ' . $this->table_prefix . self::MCHAT_SESSIONS_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id =' . (int) $this->user->data['user_id'];
+ $this->db->sql_query($sql);
+ }
+ }
+ return;
+ }
+
+ // mChat add-on Topic Notification
+ /**
+ * @param mixed $post_id limits deletion to a post_id in the forum
+ */
+ function mchat_delete_topic($post_id)
+ {
+ if (!isset($post_id) || empty($post_id))
+ {
+ return;
+ }
+
+ $sql = 'DELETE FROM ' . $this->table_prefix . self::MCHAT_TABLE . ' WHERE post_id = ' . (int) $post_id;
+ $this->db->sql_query($sql);
+
+ return;
+ }
+
+ // mchat_prune
+ // AutoPrune Chats
+ /**
+ * @param mixed $mchat_prune_amount set from mchat config entry
+ */
+ function mchat_prune($mchat_prune_amount)
+ {
+ // Run query to get the total message rows...
+ $sql = 'SELECT COUNT(message_id) AS total_messages FROM ' . $this->table_prefix . self::MCHAT_TABLE;
+ $result = $this->db->sql_query($sql);
+ $mchat_total_messages = (int) $this->db->sql_fetchfield('total_messages');
+ $this->db->sql_freeresult($result);
+
+ // count is below prune amount?
+ // do nothing
+ $prune = true;
+ if ($mchat_total_messages <= $mchat_prune_amount)
+ {
+ $prune = false;
+ }
+
+ if ($prune)
+ {
+
+ $result = $this->db->sql_query_limit('SELECT * FROM '. $this->table_prefix . self::MCHAT_TABLE . ' ORDER BY message_id ASC', 1);
+ $row = $this->db->sql_fetchrow($result);
+ $first_id = (int) $row['message_id'];
+
+ $this->db->sql_freeresult($result);
+
+ // compute the delete id
+ $delete_id = $mchat_total_messages - $mchat_prune_amount + $first_id;
+
+ // let's go delete them...if the message id is less than the delete id
+ $sql = 'DELETE FROM ' . $this->table_prefix . self::MCHAT_TABLE . '
+ WHERE message_id < ' . (int) $delete_id;
+ $this->db->sql_query($sql);
+
+ add_log('admin', 'LOG_MCHAT_TABLE_PRUNED');
+ }
+ // free up some memory...variable(s) are no longer needed.
+ unset($mchat_total_messages);
+
+ // return to what we were doing
+ return;
+
+ }
+ // display_mchat_bbcodes
+ // can't use the default phpBB one but
+ // most of code is from similar function
+ /**
+ * @param mixed $mchat_prune_amount set from mchat config entry
+ */
+ function display_mchat_bbcodes()
+ {
+ // grab the bbcodes that aren't allowed
+ $config_mchat = $this->cache->get('_mchat_config');
+
+ $disallowed_bbcode_array = explode('|', strtoupper($config_mchat['bbcode_disallowed']));
+ preg_replace('#^(.*?)=#si','$1',$disallowed_bbcode_array);
+ $default_bbcodes = array('b','i','u','quote','code','list','img','url','size','color','email','flash');
+
+ // let's remove the default bbcodes
+ if (sizeof($disallowed_bbcode_array))
+ {
+ foreach ($default_bbcodes as $default_bbcode)
+ {
+ $default_bbcode = strtoupper($default_bbcode);
+ if (!in_array($default_bbcode, $disallowed_bbcode_array))
+ {
+ $this->template->assign_vars(array(
+ 'S_MCHAT_BBCODE_'.$default_bbcode => true,
+ ));
+ }
+ }
+ }
+
+ // now for the custom bbcodes
+ // Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing)
+ $num_predefined_bbcodes = 22;
+
+ $sql = 'SELECT bbcode_id, bbcode_tag, bbcode_helpline
+ FROM ' . BBCODES_TABLE . '
+ WHERE display_on_posting = 1
+ ORDER BY bbcode_tag';
+ $result = $this->db->sql_query($sql);
+
+ $i = 0;
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $bbcode_tag_name = strtoupper($row['bbcode_tag']);
+ if (sizeof($disallowed_bbcode_array))
+ {
+ if (in_array($bbcode_tag_name, $disallowed_bbcode_array))
+ {
+ continue;
+ }
+ }
+ // If the helpline is defined within the language file, we will use the localised version, else just use the database entry...
+ if (isset($this->user->lang[strtoupper($row['bbcode_helpline'])]))
+ {
+ $row['bbcode_helpline'] = $this->user->lang[strtoupper($row['bbcode_helpline'])];
+ }
+
+ $this->template->assign_block_vars('custom_tags', array(
+ 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'",
+ 'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2),
+ 'BBCODE_TAG' => $row['bbcode_tag'],
+ 'BBCODE_HELPLINE' => $row['bbcode_helpline'],
+ 'A_BBCODE_HELPLINE' => str_replace(array('&', '"', "'", '<', '>'), array('&', '"', "\'", '<', '>'), $row['bbcode_helpline']),
+ ));
+
+ $i++;
+ }
+ $this->db->sql_freeresult($result);
+ }
+}
\ No newline at end of file
diff --git a/event/listener.php b/event/listener.php
new file mode 100644
index 0000000..cf11347
--- /dev/null
+++ b/event/listener.php
@@ -0,0 +1,59 @@
+config = $config;
+ $this->template = $template;
+ $this->user = $user;
+ $this->db = $db;
+ $this->root_path = $root_path;
+ $this->php_ext = $php_ext;
+ $this->auth = $auth;
+ }
+
+ static public function getSubscribedEvents()
+ {
+ return array(
+ 'core.user_setup' => 'load_language_on_setup',
+ );
+ }
+
+ public function load_language_on_setup($event)
+ {
+ $lang_set_ext = $event['lang_set_ext'];
+ $lang_set_ext[] = array(
+ 'ext_name' => 'dmzx/mchat',
+ 'lang_set' => 'common',
+ );
+ $event['lang_set_ext'] = $lang_set_ext;
+ }
+}
\ No newline at end of file
diff --git a/ext.php b/ext.php
new file mode 100644
index 0000000..de93c60
--- /dev/null
+++ b/ext.php
@@ -0,0 +1,18 @@
+ 'Mini-Chat',
+ 'MCHAT_ADD' => 'Send',
+ 'MCHAT_ANNOUNCEMENT' => 'Announcement',
+ 'MCHAT_ARCHIVE' => 'Archive',
+ 'MCHAT_ARCHIVE_PAGE' => 'Mini-Chat Archive',
+ 'MCHAT_BBCODES' => 'BBCodes',
+ 'MCHAT_CLEAN' => 'Purge',
+ 'MCHAT_CLEANED' => 'All messages have been successfully removed',
+ 'MCHAT_CLEAR_INPUT' => 'Reset',
+ 'MCHAT_COPYRIGHT' => 'RMcGirr83 © dmzx ',
+ 'MCHAT_CUSTOM_BBCODES' => 'Custom BBCodes',
+ 'MCHAT_DELALLMESS' => 'Remove all messages?',
+ 'MCHAT_DELCONFIRM' => 'Do you confirm removal?',
+ 'MCHAT_DELITE' => 'Delete',
+ 'MCHAT_EDIT' => 'Edit',
+ 'MCHAT_EDITINFO' => 'Edit the message and click OK',
+ 'MCHAT_ENABLE' => 'Sorry, the Mini-Chat is currently unavailable',
+ 'MCHAT_ERROR' => 'Error',
+ 'MCHAT_FLOOD' => 'You can not post another message so soon after your last',
+ 'MCHAT_FOE' => 'This message was made by %1$s who is currently on your ignore list.',
+ 'MCHAT_HELP' => 'mChat Rules',
+ 'MCHAT_HIDE_LIST' => 'Hide List',
+ 'MCHAT_HOUR' => 'hour ',
+ 'MCHAT_HOURS' => 'hours',
+ 'MCHAT_IP' => 'IP whois for',
+
+ 'MCHAT_MINUTE' => 'minute ',
+ 'MCHAT_MINUTES' => 'minutes ',
+ 'MCHAT_MESS_LONG' => 'Your message is too long.\nPlease limit it to %s characters',
+ 'MCHAT_NO_CUSTOM_PAGE' => 'The mChat custom page is not activated at this time!',
+ 'MCHAT_NOACCESS' => 'You don’t have permission to post in the mChat',
+ 'MCHAT_NOACCESS_ARCHIVE' => 'You don’t have permission to view the archive',
+ 'MCHAT_NOJAVASCRIPT' => 'Your browser does not support JavaScript or JavaScript is disabled',
+ 'MCHAT_NOMESSAGE' => 'No messages',
+ 'MCHAT_NOMESSAGEINPUT' => 'You have not entered a message',
+ 'MCHAT_NOSMILE' => 'Smilies not found',
+ 'MCHAT_NOTINSTALLED_USER' => 'mChat is not installed. Please notify the board founder.',
+ 'MCHAT_NOT_INSTALLED' => 'mChat database entries are missing. Please run the %sinstaller%s to make the database changes for the modification.',
+ 'MCHAT_OK' => 'OK',
+ 'MCHAT_PAUSE' => 'Paused',
+ 'MCHAT_LOAD' => 'Loading',
+ 'MCHAT_PERMISSIONS' => 'Change users permissions',
+ 'MCHAT_REFRESHING' => 'Refreshing...',
+ 'MCHAT_REFRESH_NO' => 'Autoupdate is off',
+ 'MCHAT_REFRESH_YES' => 'Autoupdate every %d seconds',
+ 'MCHAT_RESPOND' => 'Respond to user',
+ 'MCHAT_RESET_QUESTION' => 'Clear the input area?',
+ 'MCHAT_SESSION_OUT' => 'Chat session has expired',
+ 'MCHAT_SHOW_LIST' => 'Show List',
+ 'MCHAT_SECOND' => 'second ',
+ 'MCHAT_SECONDS' => 'seconds ',
+ 'MCHAT_SESSION_ENDS' => 'Chat session ends in',
+ 'MCHAT_SMILES' => 'Smilies',
+
+ 'MCHAT_TOTALMESSAGES' => 'Total messages: %s ',
+ 'MCHAT_USESOUND' => 'Use sound?',
+
+
+ 'MCHAT_ONLINE_USERS_TOTAL' => 'In total there are %d users chatting ',
+ 'MCHAT_ONLINE_USER_TOTAL' => 'In total there is %d user chatting ',
+ 'MCHAT_NO_CHATTERS' => 'No one is chatting',
+ 'MCHAT_ONLINE_EXPLAIN' => 'based on users active over the past %s',
+
+ 'WHO_IS_CHATTING' => 'Who is chatting',
+ 'WHO_IS_REFRESH_EXPLAIN' => 'Refreshes every %d seconds',
+ 'MCHAT_NEW_TOPIC' => 'New Topic ',
+ 'MCHAT_NEW_REPLY' => 'New Reply ',
+
+ // UCP
+ 'UCP_PROFILE_MCHAT' => 'mChat Preferences',
+
+ 'DISPLAY_MCHAT' => 'Display mChat on Index',
+ 'SOUND_MCHAT' => 'Enable mChat sound',
+ 'DISPLAY_STATS_INDEX' => 'Display the Who is Chatting stats on index page',
+ 'DISPLAY_NEW_TOPICS' => 'Display new topics in the chat',
+ 'DISPLAY_AVATARS' => 'Display avatars in the chat',
+ 'CHAT_AREA' => 'Input type',
+ 'CHAT_AREA_EXPLAIN' => 'Choose which type of area to use to input a chat: A text area or an input area',
+ 'INPUT_AREA' => 'Input area',
+ 'TEXT_AREA' => 'Text area',
+ // ACP
+ 'ACP_MCHAT_RULES_EXPLAIN' => 'Enter the rules of the forum here. Each rule on a new line. You are limited to 255 characters.This message can be translated. (you must edit the mchat_lang.php file and read the instructions).',
+ 'LOG_MCHAT_CONFIG_UPDATE' => 'Updated mChat config ',
+ 'MCHAT_CONFIG_SAVED' => 'Mini Chat configuration has been updated',
+ 'MCHAT_TITLE' => 'Mini-Chat',
+ 'MCHAT_VERSION' => 'Version:',
+ 'MCHAT_ENABLE' => 'Enable mChat Extension',
+ 'MCHAT_ENABLE_EXPLAIN' => 'Enable or disable the extension globally.',
+ 'MCHAT_AVATARS' => 'Display avatars',
+ 'MCHAT_AVATARS_EXPLAIN' => 'If set yes, resized user avatars will be displayed',
+ 'MCHAT_ON_INDEX' => 'mChat On Index',
+ 'MCHAT_ON_INDEX_EXPLAIN' => 'Allow the display of the mChat on the index page.',
+ 'MCHAT_INDEX_HEIGHT' => 'Index Page Height',
+ 'MCHAT_INDEX_HEIGHT_EXPLAIN' => 'The height of the chat box in pixels on the index page of the forum.You are limited from 50 to 1000 .',
+ 'MCHAT_LOCATION' => 'Location on Forum',
+ 'MCHAT_LOCATION_EXPLAIN' => 'Choose the location of the mChat on the index page.',
+ 'MCHAT_TOP_OF_FORUM' => 'Top of Forum',
+ 'MCHAT_BOTTOM_OF_FORUM' => 'Bottom of Forum',
+ 'MCHAT_REFRESH' => 'Refresh',
+ 'MCHAT_REFRESH_EXPLAIN' => 'Number of seconds before chat automatically refreshes.You are limited from 5 to 60 seconds .',
+ 'MCHAT_PRUNE' => 'Enable Prune',
+ 'MCHAT_PRUNE_EXPLAIN' => 'Set to yes to enable the prune feature.Only occurs if a user views the custom or archive pages .',
+ 'MCHAT_PRUNE_NUM' => 'Prune Number',
+ 'MCHAT_PRUNE_NUM_EXPLAIN' => 'The number of messages to retain in the chat.',
+ 'MCHAT_MESSAGE_LIMIT' => 'Message limit',
+ 'MCHAT_MESSAGE_LIMIT_EXPLAIN' => 'The maximum number of messages to show in the chat area.Recommended from 10 to 30 .',
+ 'MCHAT_MESSAGE_NUM' => 'Index page message limit',
+ 'MCHAT_MESSAGE_NUM_EXPLAIN' => 'The maximum number of messages to show in the chat area on the index page.Recommended from 10 to 50 .',
+ 'MCHAT_ARCHIVE_LIMIT' => 'Archive limit',
+ 'MCHAT_ARCHIVE_LIMIT_EXPLAIN' => 'The maximum number of messages to show per page on the archive page. Recommended from 25 to 50 .',
+ 'MCHAT_FLOOD_TIME' => 'Flood time',
+ 'MCHAT_FLOOD_TIME_EXPLAIN' => 'The number of seconds a user must wait before posting another message in the chat.Recommended 5 to 30, set to 0 to disable .',
+ 'MCHAT_MAX_MESSAGE_LENGTH' => 'Max message length',
+ 'MCHAT_MAX_MESSAGE_LENGTH_EXPLAIN' => 'Max number of characters allowed per message posted.Recommended from 100 to 500, set to 0 to disable .',
+ 'MCHAT_CUSTOM_PAGE' => 'Custom Page',
+ 'MCHAT_CUSTOM_PAGE_EXPLAIN' => 'Allow the use of the custom page',
+ 'MCHAT_CUSTOM_HEIGHT' => 'Custom Page Height',
+ 'MCHAT_CUSTOM_HEIGHT_EXPLAIN' => 'The height of the chat box in pixels on the seperate mChat page.You are limited from 50 to 1000 .',
+ 'MCHAT_DATE_FORMAT' => 'Date format',
+ 'MCHAT_DATE_FORMAT_EXPLAIN' => 'The syntax used is identical to the PHP date() function.',
+ 'MCHAT_CUSTOM_DATEFORMAT' => 'Custom…',
+ 'MCHAT_WHOIS' => 'Whois',
+ 'MCHAT_WHOIS_EXPLAIN' => 'Allow a display of users who are chatting',
+ 'MCHAT_WHOIS_REFRESH' => 'Whois refresh',
+ 'MCHAT_WHOIS_REFRESH_EXPLAIN' => 'Number of seconds before whois stats refreshes.You are limited from 30 to 300 seconds .',
+ 'MCHAT_BBCODES_DISALLOWED' => 'Disallowed bbcodes',
+ 'MCHAT_BBCODES_DISALLOWED_EXPLAIN' => 'Here you can input the bbcodes that are not to be used in a message. Separate bbcodes with a vertical bar, for example: b|i|u|code|list|list=|flash|quote and/or a %scustom bbcode tag name%s',
+ 'MCHAT_STATIC_MESSAGE' => 'Static Message',
+ 'MCHAT_STATIC_MESSAGE_EXPLAIN' => 'Here you can define a static message to display to users of the chat. HTML code is allowed. Set to empty to disable the display. You are limited to 255 characters.This message can be translated. (you must edit the mchat_lang.php file and read the instructions).',
+ 'MCHAT_USER_TIMEOUT' => 'User Timeout',
+ 'MCHAT_USER_TIMEOUT_EXPLAIN' => 'Set the amount of time, in seconds, until a users session in the chat ends. Set to 0 for no timeout.You are limited to the %sforum config setting for sessions%s which is currently set to %s seconds ',
+ 'MCHAT_OVERRIDE_SMILIE_LIMIT' => 'Override smilie limit',
+ 'MCHAT_OVERRIDE_SMILIE_LIMIT_EXPLAIN' => 'Set to yes to override the forums smilie limit setting for chat messages',
+ 'MCHAT_OVERRIDE_MIN_POST_CHARS' => 'Override minimum characters limit',
+ 'MCHAT_OVERRIDE_MIN_POST_CHARS_EXPLAIN' => 'Set to yes to override the forums minimum characters setting for chat messages',
+ 'MCHAT_NEW_POSTS' => 'Display New Posts',
+ 'MCHAT_NEW_POSTS_EXPLAIN' => 'Set to yes to allow new posts from the forum to be posted into the chat message areaYou must have the add-on for new post notifications installed (within the contrib directory of the extension download).',
+ 'MCHAT_MAIN' => 'Main Configuration',
+ 'MCHAT_STATS' => 'Whois Chatting',
+ 'MCHAT_STATS_INDEX' => 'Stats on Index',
+ 'MCHAT_STATS_INDEX_EXPLAIN' => 'Show who is chatting with in the stats section of the forum',
+ 'MCHAT_MESSAGES' => 'Message Settings',
+ 'MCHAT_PAUSE_ON_INPUT' => 'Pause on input',
+ 'MCHAT_PAUSE_ON_INPUT_EXPLAIN' => 'If set Yes, then the chat will not autoupdate upon a user entering a message in the input area',
+
+ // error reporting
+ 'MCHAT_NEEDS_UPDATING' => 'The mChat extension needs updating. Please have a forum founder visit this section to run the installer.',
+ 'MCHAT_WRONG_VERSION' => 'The wrong version of the extension is installed. Please run the %sinstaller%s for the new version of the modification.',
+ 'WARNING' => 'Warning',
+ 'TOO_LONG_DATE' => 'The date format you entered is too long.',
+ 'TOO_SHORT_DATE' => 'The date format you entered is too short.',
+ 'TOO_SMALL_REFRESH' => 'The refresh value is too small.',
+ 'TOO_LARGE_REFRESH' => 'The refresh value is too large.',
+ 'TOO_SMALL_MESSAGE_LIMIT' => 'The message limit value is too small.',
+ 'TOO_LARGE_MESSAGE_LIMIT' => 'The message limit value is too large.',
+ 'TOO_SMALL_ARCHIVE_LIMIT' => 'The archive limit value is too small.',
+ 'TOO_LARGE_ARCHIVE_LIMIT' => 'The archive limit value is too large.',
+ 'TOO_SMALL_FLOOD_TIME' => 'The flood time value is too small.',
+ 'TOO_LARGE_FLOOD_TIME' => 'The flood time value is too large.',
+ 'TOO_SMALL_MAX_MESSAGE_LNGTH' => 'The max message length value is too small.',
+ 'TOO_LARGE_MAX_MESSAGE_LNGTH' => 'The max message length value is too large.',
+ 'TOO_SMALL_MAX_WORDS_LNGTH' => 'The max words length value is too small.',
+ 'TOO_LARGE_MAX_WORDS_LNGTH' => 'The max words length value is too large.',
+ 'TOO_SMALL_WHOIS_REFRESH' => 'The whois refresh value is too small.',
+ 'TOO_LARGE_WHOIS_REFRESH' => 'The whois refresh value is too large.',
+ 'TOO_SMALL_INDEX_HEIGHT' => 'The index height value is too small.',
+ 'TOO_LARGE_INDEX_HEIGHT' => 'The index height value is too large.',
+ 'TOO_SMALL_CUSTOM_HEIGHT' => 'The custom height value is too small.',
+ 'TOO_LARGE_CUSTOM_HEIGHT' => 'The custom height value is too large.',
+ 'TOO_SHORT_STATIC_MESSAGE' => 'The static message value is too short.',
+ 'TOO_LONG_STATIC_MESSAGE' => 'The static message value is too long.',
+ 'TOO_SMALL_TIMEOUT' => 'The user timeout value is too small.',
+ 'TOO_LARGE_TIMEOUT' => 'The user timeout value is too large.',
+ 'UCP_CAT_MCHAT' => 'mChat',
+ 'UCP_MCHAT_CONFIG' => 'mChat', //Preferences
+ 'LOG_MCHAT_TABLE_PRUNED' => 'mChat Table was pruned',
+ 'ACP_USER_MCHAT' => 'mChat Settings',
+ 'LOG_DELETED_MCHAT' => 'Deleted mChat message » %1$s',
+ 'LOG_EDITED_MCHAT' => 'Edited mChat message » %1$s',
+ 'MCHAT_MESSAGE_LNGTH_EXPLAIN' => 'Characters remaining: %d ',
+ 'MCHAT_TOP_POSTERS' => 'Top Spammers',
+ 'MCHAT_NEW_CHAT' => 'New Chat Message!',
+ 'FONT_COLOR' => 'Font colour',
+ 'FONT_COLOR_HIDE' => 'Hide font colour',
+ 'FONT_HUGE' => 'Huge',
+ 'FONT_LARGE' => 'Large',
+ 'FONT_NORMAL' => 'Normal',
+ 'FONT_SIZE' => 'Font size',
+ 'FONT_SMALL' => 'Small',
+ 'FONT_TINY' => 'Tiny',
+ 'MCHAT_SEND_PM' => 'Send Private Message',
+ 'MCHAT_PM' => '(PM)',
+ 'MORE_SMILIES' => 'More Smilies',
+));
\ No newline at end of file
diff --git a/language/en/info_acp_mchat.php b/language/en/info_acp_mchat.php
new file mode 100644
index 0000000..b0ee155
--- /dev/null
+++ b/language/en/info_acp_mchat.php
@@ -0,0 +1,159 @@
+ 'Configuration',
+ 'ACP_CAT_MCHAT' => 'mChat',
+ 'ACP_MCHAT_TITLE' => 'Mini-Chat',
+ 'ACP_MCHAT_TITLE_EXPLAIN' => 'A mini chat (aka “shout box”) for your forum',
+ 'MCHAT_TABLE_DELETED' => 'The mChat table was successfully deleted',
+ 'MCHAT_TABLE_CREATED' => 'The mChat table was successfully created',
+ 'MCHAT_TABLE_UPDATED' => 'The mChat table was successfully updated',
+ 'MCHAT_NOTHING_TO_UPDATE' => 'Nothing to do....continuing',
+ 'UCP_CAT_MCHAT' => 'mChat Prefs',
+ 'UCP_MCHAT_CONFIG' => 'User mChat Prefs',
+
+ // ACP entries
+ 'ACP_MCHAT_RULES' => 'Rules',
+ 'ACP_MCHAT_RULES_EXPLAIN' => 'Enter the rules of the forum here. Each rule on a new line. You are limited to 255 characters.This message can be translated. (you must edit the mchat_lang.php file and read the instructions).',
+ 'LOG_MCHAT_CONFIG_UPDATE' => 'Updated mChat config ',
+ 'MCHAT_CONFIG_SAVED' => 'Mini Chat configuration has been updated',
+ 'MCHAT_TITLE' => 'Mini-Chat',
+ 'MCHAT_VERSION' => 'Version:',
+ 'MCHAT_ENABLE' => 'Enable mChat Extension',
+ 'MCHAT_ENABLE_EXPLAIN' => 'Enable or disable the extension globally.',
+ 'MCHAT_AVATARS' => 'Display avatars',
+ 'MCHAT_AVATARS_EXPLAIN' => 'If set yes, resized user avatars will be displayed',
+ 'MCHAT_ON_INDEX' => 'mChat On Index',
+ 'MCHAT_ON_INDEX_EXPLAIN' => 'Allow the display of the mChat on the index page.',
+ 'MCHAT_INDEX_HEIGHT' => 'Index Page Height',
+ 'MCHAT_INDEX_HEIGHT_EXPLAIN' => 'The height of the chat box in pixels on the index page of the forum.You are limited from 50 to 1000 .',
+ 'MCHAT_LOCATION' => 'Location on Forum',
+ 'MCHAT_LOCATION_EXPLAIN' => 'Choose the location of the mChat on the index page.',
+ 'MCHAT_TOP_OF_FORUM' => 'Top of Forum',
+ 'MCHAT_BOTTOM_OF_FORUM' => 'Bottom of Forum',
+ 'MCHAT_REFRESH' => 'Refresh',
+ 'MCHAT_REFRESH_EXPLAIN' => 'Number of seconds before chat automatically refreshes.You are limited from 5 to 60 seconds .',
+ 'MCHAT_PRUNE' => 'Enable Prune',
+ 'MCHAT_PRUNE_EXPLAIN' => 'Set to yes to enable the prune feature.Only occurs if a user views the custom or archive pages .',
+ 'MCHAT_PRUNE_NUM' => 'Prune Number',
+ 'MCHAT_PRUNE_NUM_EXPLAIN' => 'The number of messages to retain in the chat.',
+ 'MCHAT_MESSAGE_LIMIT' => 'Message limit',
+ 'MCHAT_MESSAGE_LIMIT_EXPLAIN' => 'The maximum number of messages to show in the chat area.Recommended from 10 to 30 .',
+ 'MCHAT_MESSAGE_NUM' => 'Index page message limit',
+ 'MCHAT_MESSAGE_NUM_EXPLAIN' => 'The maximum number of messages to show in the chat area on the index page.Recommended from 10 to 50 .',
+ 'MCHAT_ARCHIVE_LIMIT' => 'Archive limit',
+ 'MCHAT_ARCHIVE_LIMIT_EXPLAIN' => 'The maximum number of messages to show per page on the archive page. Recommended from 25 to 50 .',
+ 'MCHAT_FLOOD_TIME' => 'Flood time',
+ 'MCHAT_FLOOD_TIME_EXPLAIN' => 'The number of seconds a user must wait before posting another message in the chat.Recommended 5 to 30, set to 0 to disable .',
+ 'MCHAT_MAX_MESSAGE_LENGTH' => 'Max message length',
+ 'MCHAT_MAX_MESSAGE_LENGTH_EXPLAIN' => 'Max number of characters allowed per message posted.Recommended from 100 to 500, set to 0 to disable .',
+ 'MCHAT_CUSTOM_PAGE' => 'Custom Page',
+ 'MCHAT_CUSTOM_PAGE_EXPLAIN' => 'Allow the use of the custom page',
+ 'MCHAT_CUSTOM_HEIGHT' => 'Custom Page Height',
+ 'MCHAT_CUSTOM_HEIGHT_EXPLAIN' => 'The height of the chat box in pixels on the seperate mChat page.You are limited from 50 to 1000 .',
+ 'MCHAT_DATE_FORMAT' => 'Date format',
+ 'MCHAT_DATE_FORMAT_EXPLAIN' => 'The syntax used is identical to the PHP date() function.',
+ 'MCHAT_CUSTOM_DATEFORMAT' => 'Custom…',
+ 'MCHAT_WHOIS' => 'Whois',
+ 'MCHAT_WHOIS_EXPLAIN' => 'Allow a display of users who are chatting',
+ 'MCHAT_WHOIS_REFRESH' => 'Whois refresh',
+ 'MCHAT_WHOIS_REFRESH_EXPLAIN' => 'Number of seconds before whois stats refreshes.You are limited from 30 to 300 seconds .',
+ 'MCHAT_BBCODES_DISALLOWED' => 'Disallowed bbcodes',
+ 'MCHAT_BBCODES_DISALLOWED_EXPLAIN' => 'Here you can input the bbcodes that are not to be used in a message. Separate bbcodes with a vertical bar, for example: b|i|u|code|list|list=|flash|quote and/or a %scustom bbcode tag name%s',
+ 'MCHAT_STATIC_MESSAGE' => 'Static Message',
+ 'MCHAT_STATIC_MESSAGE_EXPLAIN' => 'Here you can define a static message to display to users of the chat. HTML code is allowed. Set to empty to disable the display. You are limited to 255 characters.This message can be translated. (you must edit the mchat_lang.php file and read the instructions).',
+ 'MCHAT_USER_TIMEOUT' => 'User Timeout',
+ 'MCHAT_USER_TIMEOUT_EXPLAIN' => 'Set the amount of time, in seconds, until a users session in the chat ends. Set to 0 for no timeout.You are limited to the %sforum config setting for sessions%s which is currently set to %s seconds ',
+ 'MCHAT_OVERRIDE_SMILIE_LIMIT' => 'Override smilie limit',
+ 'MCHAT_OVERRIDE_SMILIE_LIMIT_EXPLAIN' => 'Set to yes to override the forums smilie limit setting for chat messages',
+ 'MCHAT_OVERRIDE_MIN_POST_CHARS' => 'Override minimum characters limit',
+ 'MCHAT_OVERRIDE_MIN_POST_CHARS_EXPLAIN' => 'Set to yes to override the forums minimum characters setting for chat messages',
+ 'MCHAT_NEW_POSTS' => 'Display New Posts',
+ 'MCHAT_NEW_POSTS_EXPLAIN' => 'Set to yes to allow new posts from the forum to be posted into the chat message areaYou must have the add-on for new post notifications installed (within the contrib directory of the extension download).',
+ 'MCHAT_MAIN' => 'Main Configuration',
+ 'MCHAT_STATS' => 'Whois Chatting',
+ 'MCHAT_STATS_INDEX' => 'Stats on Index',
+ 'MCHAT_STATS_INDEX_EXPLAIN' => 'Show who is chatting with in the stats section of the forum',
+ 'MCHAT_MESSAGES' => 'Message Settings',
+ 'MCHAT_PAUSE_ON_INPUT' => 'Pause on input',
+ 'MCHAT_PAUSE_ON_INPUT_EXPLAIN' => 'If set Yes, then the chat will not autoupdate upon a user entering a message in the input area',
+
+ // error reporting
+ 'MCHAT_NEEDS_UPDATING' => 'The mChat extension needs updating. Please have a forum founder visit this section to run the installer.',
+ 'MCHAT_WRONG_VERSION' => 'The wrong version of the extension is installed. Please run the %sinstaller%s for the new version of the modification.',
+ 'WARNING' => 'Warning',
+ 'TOO_LONG_DATE' => 'The date format you entered is too long.',
+ 'TOO_SHORT_DATE' => 'The date format you entered is too short.',
+ 'TOO_SMALL_REFRESH' => 'The refresh value is too small.',
+ 'TOO_LARGE_REFRESH' => 'The refresh value is too large.',
+ 'TOO_SMALL_MESSAGE_LIMIT' => 'The message limit value is too small.',
+ 'TOO_LARGE_MESSAGE_LIMIT' => 'The message limit value is too large.',
+ 'TOO_SMALL_ARCHIVE_LIMIT' => 'The archive limit value is too small.',
+ 'TOO_LARGE_ARCHIVE_LIMIT' => 'The archive limit value is too large.',
+ 'TOO_SMALL_FLOOD_TIME' => 'The flood time value is too small.',
+ 'TOO_LARGE_FLOOD_TIME' => 'The flood time value is too large.',
+ 'TOO_SMALL_MAX_MESSAGE_LNGTH' => 'The max message length value is too small.',
+ 'TOO_LARGE_MAX_MESSAGE_LNGTH' => 'The max message length value is too large.',
+ 'TOO_SMALL_MAX_WORDS_LNGTH' => 'The max words length value is too small.',
+ 'TOO_LARGE_MAX_WORDS_LNGTH' => 'The max words length value is too large.',
+ 'TOO_SMALL_WHOIS_REFRESH' => 'The whois refresh value is too small.',
+ 'TOO_LARGE_WHOIS_REFRESH' => 'The whois refresh value is too large.',
+ 'TOO_SMALL_INDEX_HEIGHT' => 'The index height value is too small.',
+ 'TOO_LARGE_INDEX_HEIGHT' => 'The index height value is too large.',
+ 'TOO_SMALL_CUSTOM_HEIGHT' => 'The custom height value is too small.',
+ 'TOO_LARGE_CUSTOM_HEIGHT' => 'The custom height value is too large.',
+ 'TOO_SHORT_STATIC_MESSAGE' => 'The static message value is too short.',
+ 'TOO_LONG_STATIC_MESSAGE' => 'The static message value is too long.',
+ 'TOO_SMALL_TIMEOUT' => 'The user timeout value is too small.',
+ 'TOO_LARGE_TIMEOUT' => 'The user timeout value is too large.',
+
+ // User perms
+ 'ACL_U_MCHAT_USE' => 'Can use mChat mchat',
+ 'ACL_U_MCHAT_VIEW' => 'Can view mChat mchat',
+ 'ACL_U_MCHAT_EDIT' => 'Can edit mChat messages mchat',
+ 'ACL_U_MCHAT_DELETE' => 'Can delete mChat messages mchat',
+ 'ACL_U_MCHAT_IP' => 'Can use view mChat IP addresses mchat',
+ 'ACL_U_MCHAT_FLOOD_IGNORE' => 'Can ignore mChat flood mchat',
+ 'ACL_U_MCHAT_ARCHIVE' => 'Can view the Archive mchat',
+ 'ACL_U_MCHAT_BBCODE' => 'Can use bbcode in mChat mchat',
+ 'ACL_U_MCHAT_SMILIES' => 'Can use smilies in mChat mchat',
+ 'ACL_U_MCHAT_URLS' => 'Can post urls in mChat mchat',
+
+ // Admin perms
+ 'ACL_A_MCHAT' => array('lang' => 'Can manage mChat settings', 'cat' => 'permissions'), // Using a phpBB category here
+
+));
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/migrations/mchat_module.php b/migrations/mchat_module.php
new file mode 100644
index 0000000..e4654e4
--- /dev/null
+++ b/migrations/mchat_module.php
@@ -0,0 +1,29 @@
+ '\dmzx\mchat\acp\acp_mchat_module',
+ 'modes' => array('configuration'),
+ 'module_auth' => 'a_mchat',
+ ),
+ )),
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/migrations/mchat_module1.php b/migrations/mchat_module1.php
new file mode 100644
index 0000000..9638cbd
--- /dev/null
+++ b/migrations/mchat_module1.php
@@ -0,0 +1,30 @@
+ '\dmzx\mchat\ucp\ucp_mchat_module',
+ 'modes' => array('configuration'),
+ 'module_auth' => 'acl_u_mchat_use',
+ ))),
+ );
+ }
+}
+
+
+
\ No newline at end of file
diff --git a/migrations/mchat_schema.php b/migrations/mchat_schema.php
new file mode 100644
index 0000000..6caed1b
--- /dev/null
+++ b/migrations/mchat_schema.php
@@ -0,0 +1,84 @@
+ array(
+ $this->table_prefix . 'mchat_config' => array(
+ 'COLUMNS' => array(
+ 'config_name' => array('VCHAR', ''),
+ 'config_value' => array('VCHAR', ''),
+ ),
+ 'PRIMARY_KEY' => 'config_name',
+ ),
+ ),
+ );
+ }
+
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'mchat_config',
+ ),
+ );
+ }
+
+
+}
diff --git a/migrations/mchat_schema_2.php b/migrations/mchat_schema_2.php
new file mode 100644
index 0000000..23dfbd7
--- /dev/null
+++ b/migrations/mchat_schema_2.php
@@ -0,0 +1,52 @@
+ array(
+ $this->table_prefix . 'mchat' => array(
+ 'COLUMNS' => array(
+ 'message_id' => array('UINT', NULL, 'auto_increment'),
+ 'user_id' => array('UINT', 0),
+ 'user_ip' => array('VCHAR:40', ''),
+ 'message' => array('MTEXT_UNI', ''),
+ 'bbcode_bitfield' => array('VCHAR', ''),
+ 'bbcode_uid' => array('VCHAR:8', ''),
+ 'bbcode_options' => array('BOOL', '7'),
+ 'message_time' => array('INT:11', 0),
+ 'forum_id' => array('UINT', 0),
+ 'post_id' => array('UINT', 0),
+ ),
+ 'PRIMARY_KEY' => 'message_id',
+ ),
+ ),
+ );
+ }
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'mchat',
+ ),
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/migrations/mchat_schema_3.php b/migrations/mchat_schema_3.php
new file mode 100644
index 0000000..891b007
--- /dev/null
+++ b/migrations/mchat_schema_3.php
@@ -0,0 +1,132 @@
+ 'refresh',
+ 'config_value' => '10',
+ ),
+ array(
+ 'config_name' => 'message_limit',
+ 'config_value' => '10',
+ ),
+ array(
+ 'config_name' => 'archive_limit',
+ 'config_value' => '25',
+ ),
+ array(
+ 'config_name' => 'flood_time',
+ 'config_value' => '20',
+ ),
+ array(
+ 'config_name' => 'max_message_lngth',
+ 'config_value' => '500',
+ ),
+ array(
+ 'config_name' => 'custom_page',
+ 'config_value' => '1',
+ ),
+ array(
+ 'config_name' => 'date',
+ 'config_value' => 'D M d, Y g:i a',
+ ),
+ array(
+ 'config_name' => 'whois',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'bbcode_disallowed',
+ 'config_value' => '',
+ ),
+ array(
+ 'config_name' => 'prune_enable',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'prune_num',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'location',
+ 'config_value' => '1',
+ ),
+ array(
+ 'config_name' => 'whois_refresh',
+ 'config_value' => '30',
+ ),
+ array(
+ 'config_name' => 'static_message',
+ 'config_value' => '',
+ ),
+ array(
+ 'config_name' => 'index_height',
+ 'config_value' => '250',
+ ),
+ array(
+ 'config_name' => 'custom_height',
+ 'config_value' => '350',
+ ),
+ array(
+ 'config_name' => 'override_min_post_chars',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'timeout',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'override_smilie_limit',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'pause_on_input',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'rules',
+ 'config_value' => '',
+ ),
+ array(
+ 'config_name' => 'avatars',
+ 'config_value' => '0',
+ ),
+ array(
+ 'config_name' => 'message_num',
+ 'config_value' => '10',
+ ),
+ );
+
+ // Insert sample PM data
+ $this->db->sql_multi_insert($this->table_prefix . 'mchat_config', $sample_data);
+ }
+}
\ No newline at end of file
diff --git a/migrations/mchat_schema_4.php b/migrations/mchat_schema_4.php
new file mode 100644
index 0000000..da132b9
--- /dev/null
+++ b/migrations/mchat_schema_4.php
@@ -0,0 +1,36 @@
+ array(
+ $this->table_prefix . 'users' => array(
+ 'user_mchat_index' => array('BOOL', '1'),
+ 'user_mchat_sound' => array('BOOL', '1'),
+ 'user_mchat_stats_index' => array('BOOL', '1'),
+ 'user_mchat_topics' => array('BOOL', '1'),
+ 'user_mchat_avatars' => array('BOOL', '1'),
+ 'user_mchat_input_area' => array('BOOL', '1'),
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/migrations/mchat_schema_5.php b/migrations/mchat_schema_5.php
new file mode 100644
index 0000000..d4816cb
--- /dev/null
+++ b/migrations/mchat_schema_5.php
@@ -0,0 +1,45 @@
+ array(
+ $this->table_prefix . 'mchat_sessions' => array(
+ 'COLUMNS' => array(
+ 'user_id' => array('UINT', 0),
+ 'user_lastupdate' => array('TIMESTAMP', 0),
+ 'user_ip' => array('VCHAR:40', ''),
+ ),
+ 'PRIMARY_KEY' => 'user_id',
+ ),
+ ),
+ );
+ }
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'mchat_sessions',
+ ),
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/migrations/mchat_schema_6.php b/migrations/mchat_schema_6.php
new file mode 100644
index 0000000..4959c98
--- /dev/null
+++ b/migrations/mchat_schema_6.php
@@ -0,0 +1,47 @@
+ 'users',
+ 'module_enabled' => 1,
+ 'module_display' => 0,
+ 'module_langname' => 'ACP_USER_MCHAT',
+ 'module_mode' => 'mchat',
+ 'module_auth' => 'acl_a_user',
+ ),
+ ),
+ // First, lets add a new category named UCP_CAT_MCHAT
+ array('ucp', false, 'UCP_CAT_MCHAT'),
+
+ // next let's add our module
+ array('ucp', 'UCP_CAT_MCHAT', array(
+ 'module_basename' => 'mchat',
+ 'modes' => array('configuration'),
+ 'module_auth' => 'u_mchat_use',
+ ),
+ ),
+
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/styles/prosilver/template/editor.js b/styles/prosilver/template/editor.js
new file mode 100644
index 0000000..3766309
--- /dev/null
+++ b/styles/prosilver/template/editor.js
@@ -0,0 +1,465 @@
+/**
+* bbCode control by subBlue design [ www.subBlue.com ]
+* Includes unixsafe colour palette selector by SHS`
+*/
+
+// Startup variables
+var imageTag = false;
+var theSelection = false;
+
+var bbcodeEnabled = true;
+// Check for Browser & Platform for PC & IE specific bits
+// More details from: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
+var clientPC = navigator.userAgent.toLowerCase(); // Get client info
+var clientVer = parseInt(navigator.appVersion); // Get browser version
+
+var is_ie = ((clientPC.indexOf('msie') != -1) && (clientPC.indexOf('opera') == -1));
+var is_win = ((clientPC.indexOf('win') != -1) || (clientPC.indexOf('16bit') != -1));
+var baseHeight;
+
+/**
+* Shows the help messages in the helpline window
+*/
+function helpline(help)
+{
+ document.forms[form_name].helpbox.value = help_line[help];
+}
+
+/**
+* Fix a bug involving the TextRange object. From
+* http://www.frostjedi.com/terra/scripts/demo/caretBug.html
+*/
+function initInsertions()
+{
+ var doc;
+
+ if (document.forms[form_name])
+ {
+ doc = document;
+ }
+ else
+ {
+ doc = opener.document;
+ }
+
+ var textarea = doc.forms[form_name].elements[text_name];
+
+ if (is_ie && typeof(baseHeight) != 'number')
+ {
+ /* === mChat focus fix Start === */
+ var mChatFocus = window.mChatFocusFix || false;
+ if(!mChatFocus)
+ {
+ textarea.focus();
+ }
+ baseHeight = doc.selection.createRange().duplicate().boundingHeight;
+ /* ==== mChat focus fix End ==== */
+ if (!document.forms[form_name])
+ {
+ document.body.focus();
+ }
+ }
+}
+
+/**
+* bbstyle
+*/
+function bbstyle(bbnumber)
+{
+ if (bbnumber != -1)
+ {
+ bbfontstyle(bbtags[bbnumber], bbtags[bbnumber+1]);
+ }
+ else
+ {
+ insert_text('[*]');
+ document.forms[form_name].elements[text_name].focus();
+ }
+}
+
+
+/**
+* Apply bbcodes
+*/
+function bbfontstyle(bbopen, bbclose)
+{
+ theSelection = false;
+
+ var textarea = document.forms[form_name].elements[text_name];
+
+ textarea.focus();
+
+ if ((clientVer >= 4) && is_ie && is_win)
+ {
+ // Get text selection
+ theSelection = document.selection.createRange().text;
+
+ if (theSelection)
+ {
+ // Add tags around selection
+ document.selection.createRange().text = bbopen + theSelection + bbclose;
+ document.forms[form_name].elements[text_name].focus();
+ theSelection = '';
+ return;
+ }
+ }
+ else if (document.forms[form_name].elements[text_name].selectionEnd && (document.forms[form_name].elements[text_name].selectionEnd - document.forms[form_name].elements[text_name].selectionStart > 0))
+ {
+ mozWrap(document.forms[form_name].elements[text_name], bbopen, bbclose);
+ document.forms[form_name].elements[text_name].focus();
+ theSelection = '';
+ return;
+ }
+
+ //The new position for the cursor after adding the bbcode
+ var caret_pos = getCaretPosition(textarea).start;
+ var new_pos = caret_pos + bbopen.length;
+
+ // Open tag
+ insert_text(bbopen + bbclose);
+
+ // Center the cursor when we don't have a selection
+ // Gecko and proper browsers
+ if (!isNaN(textarea.selectionStart))
+ {
+ textarea.selectionStart = new_pos;
+ textarea.selectionEnd = new_pos;
+ }
+ // IE
+ else if (document.selection)
+ {
+ var range = textarea.createTextRange();
+ range.move("character", new_pos);
+ range.select();
+ storeCaret(textarea);
+ }
+
+ textarea.focus();
+ return;
+}
+
+/**
+* Insert text at position
+*/
+function insert_text(text, spaces, popup)
+{
+ var textarea;
+
+ if (!popup)
+ {
+ textarea = document.forms[form_name].elements[text_name];
+ }
+ else
+ {
+ textarea = opener.document.forms[form_name].elements[text_name];
+ }
+ if (spaces)
+ {
+ text = ' ' + text + ' ';
+ }
+
+ // Since IE9, IE also has textarea.selectionStart, but it still needs to be treated the old way.
+ // Therefore we simply add a !is_ie here until IE fixes the text-selection completely.
+ if (!isNaN(textarea.selectionStart) && !is_ie)
+ {
+ var sel_start = textarea.selectionStart;
+ var sel_end = textarea.selectionEnd;
+
+ mozWrap(textarea, text, '');
+ textarea.selectionStart = sel_start + text.length;
+ textarea.selectionEnd = sel_end + text.length;
+ }
+ else if (textarea.createTextRange && textarea.caretPos)
+ {
+ if (baseHeight != textarea.caretPos.boundingHeight)
+ {
+ textarea.focus();
+ storeCaret(textarea);
+ }
+
+ var caret_pos = textarea.caretPos;
+ caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) == ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text;
+ }
+ else
+ {
+ textarea.value = textarea.value + text;
+ }
+ if (!popup)
+ {
+ textarea.focus();
+ }
+}
+
+/**
+* Add inline attachment at position
+*/
+function attach_inline(index, filename)
+{
+ insert_text('[attachment=' + index + ']' + filename + '[/attachment]');
+ document.forms[form_name].elements[text_name].focus();
+}
+
+/**
+* Add quote text to message
+*/
+function addquote(post_id, username, l_wrote)
+{
+ var message_name = 'message_' + post_id;
+ var theSelection = '';
+ var divarea = false;
+
+ if (l_wrote === undefined)
+ {
+ // Backwards compatibility
+ l_wrote = 'wrote';
+ }
+
+ if (document.all)
+ {
+ divarea = document.all[message_name];
+ }
+ else
+ {
+ divarea = document.getElementById(message_name);
+ }
+
+ // Get text selection - not only the post content :(
+ // IE9 must use the document.selection method but has the *.getSelection so we just force no IE
+ if (window.getSelection && !is_ie && !window.opera)
+ {
+ theSelection = window.getSelection().toString();
+ }
+ else if (document.getSelection && !is_ie)
+ {
+ theSelection = document.getSelection();
+ }
+ else if (document.selection)
+ {
+ theSelection = document.selection.createRange().text;
+ }
+
+ if (theSelection == '' || typeof theSelection == 'undefined' || theSelection == null)
+ {
+ if (divarea.innerHTML)
+ {
+ theSelection = divarea.innerHTML.replace(/ /ig, '\n');
+ theSelection = theSelection.replace(/ /ig, '\n');
+ theSelection = theSelection.replace(/<\;/ig, '<');
+ theSelection = theSelection.replace(/>\;/ig, '>');
+ theSelection = theSelection.replace(/&\;/ig, '&');
+ theSelection = theSelection.replace(/ \;/ig, ' ');
+ }
+ else if (document.all)
+ {
+ theSelection = divarea.innerText;
+ }
+ else if (divarea.textContent)
+ {
+ theSelection = divarea.textContent;
+ }
+ else if (divarea.firstChild.nodeValue)
+ {
+ theSelection = divarea.firstChild.nodeValue;
+ }
+ }
+
+ if (theSelection)
+ {
+ if (bbcodeEnabled)
+ {
+ insert_text('[quote="' + username + '"]' + theSelection + '[/quote]');
+ }
+ else
+ {
+ insert_text(username + ' ' + l_wrote + ':' + '\n');
+ var lines = split_lines(theSelection);
+ for (i = 0; i < lines.length; i++)
+ {
+ insert_text('> ' + lines[i] + '\n');
+ }
+ }
+ }
+
+ return;
+}
+
+function split_lines(text)
+{
+ var lines = text.split('\n');
+ var splitLines = new Array();
+ var j = 0;
+ for(i = 0; i < lines.length; i++)
+ {
+ if (lines[i].length <= 80)
+ {
+ splitLines[j] = lines[i];
+ j++;
+ }
+ else
+ {
+ var line = lines[i];
+ do
+ {
+ var splitAt = line.indexOf(' ', 80);
+
+ if (splitAt == -1)
+ {
+ splitLines[j] = line;
+ j++;
+ }
+ else
+ {
+ splitLines[j] = line.substring(0, splitAt);
+ line = line.substring(splitAt);
+ j++;
+ }
+ }
+ while(splitAt != -1);
+ }
+ }
+ return splitLines;
+}
+/**
+* From http://www.massless.org/mozedit/
+*/
+function mozWrap(txtarea, open, close)
+{
+ var selLength = (typeof(txtarea.textLength) == 'undefined') ? txtarea.value.length : txtarea.textLength;
+ var selStart = txtarea.selectionStart;
+ var selEnd = txtarea.selectionEnd;
+ var scrollTop = txtarea.scrollTop;
+
+ if (selEnd == 1 || selEnd == 2)
+ {
+ selEnd = selLength;
+ }
+
+ var s1 = (txtarea.value).substring(0,selStart);
+ var s2 = (txtarea.value).substring(selStart, selEnd);
+ var s3 = (txtarea.value).substring(selEnd, selLength);
+
+ txtarea.value = s1 + open + s2 + close + s3;
+ txtarea.selectionStart = selStart + open.length;
+ txtarea.selectionEnd = selEnd + open.length;
+ txtarea.focus();
+ txtarea.scrollTop = scrollTop;
+
+ return;
+}
+
+/**
+* Insert at Caret position. Code from
+* http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130
+*/
+function storeCaret(textEl)
+{
+ if (textEl.createTextRange)
+ {
+ textEl.caretPos = document.selection.createRange().duplicate();
+ }
+}
+
+/**
+* Color pallette
+*/
+function colorPalette(dir, width, height)
+{
+ var r = 0, g = 0, b = 0;
+ var numberList = new Array(6);
+ var color = '';
+
+ numberList[0] = '00';
+ numberList[1] = '40';
+ numberList[2] = '80';
+ numberList[3] = 'BF';
+ numberList[4] = 'FF';
+
+ document.writeln('');
+
+ for (r = 0; r < 5; r++)
+ {
+ if (dir == 'h')
+ {
+ document.writeln('');
+ }
+
+ for (g = 0; g < 5; g++)
+ {
+ if (dir == 'v')
+ {
+ document.writeln(' ');
+ }
+
+ for (b = 0; b < 5; b++)
+ {
+ color = String(numberList[r]) + String(numberList[g]) + String(numberList[b]);
+ document.write('');
+ document.write(' ');
+ document.writeln(' ');
+ }
+
+ if (dir == 'v')
+ {
+ document.writeln(' ');
+ }
+ }
+
+ if (dir == 'h')
+ {
+ document.writeln('');
+ }
+ }
+ document.writeln('
');
+}
+
+
+/**
+* Caret Position object
+*/
+function caretPosition()
+{
+ var start = null;
+ var end = null;
+}
+
+
+/**
+* Get the caret position in an textarea
+*/
+function getCaretPosition(txtarea)
+{
+ var caretPos = new caretPosition();
+
+ // simple Gecko/Opera way
+ if(txtarea.selectionStart || txtarea.selectionStart == 0)
+ {
+ caretPos.start = txtarea.selectionStart;
+ caretPos.end = txtarea.selectionEnd;
+ }
+ // dirty and slow IE way
+ else if(document.selection)
+ {
+
+ // get current selection
+ var range = document.selection.createRange();
+
+ // a new selection of the whole textarea
+ var range_all = document.body.createTextRange();
+ range_all.moveToElementText(txtarea);
+
+ // calculate selection start point by moving beginning of range_all to beginning of range
+ var sel_start;
+ for (sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start++)
+ {
+ range_all.moveStart('character', 1);
+ }
+
+ txtarea.sel_start = sel_start;
+
+ // we ignore the end value for IE, this is already dirty enough and we don't need it
+ caretPos.start = txtarea.sel_start;
+ caretPos.end = txtarea.sel_start;
+ }
+
+ return caretPos;
+}
diff --git a/styles/prosilver/template/event/index_body_block_online_append.html b/styles/prosilver/template/event/index_body_block_online_append.html
new file mode 100644
index 0000000..e8e044d
--- /dev/null
+++ b/styles/prosilver/template/event/index_body_block_online_append.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/styles/prosilver/template/event/index_body_forumlist_body_after.html b/styles/prosilver/template/event/index_body_forumlist_body_after.html
new file mode 100644
index 0000000..528c5d7
--- /dev/null
+++ b/styles/prosilver/template/event/index_body_forumlist_body_after.html
@@ -0,0 +1 @@
+
diff --git a/styles/prosilver/template/event/index_body_markforums_after.html b/styles/prosilver/template/event/index_body_markforums_after.html
new file mode 100644
index 0000000..bf8d07f
--- /dev/null
+++ b/styles/prosilver/template/event/index_body_markforums_after.html
@@ -0,0 +1 @@
+
diff --git a/styles/prosilver/template/event/overall_footer_after.html b/styles/prosilver/template/event/overall_footer_after.html
new file mode 100644
index 0000000..6c99116
--- /dev/null
+++ b/styles/prosilver/template/event/overall_footer_after.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/styles/prosilver/template/event/overall_header_body_before.html b/styles/prosilver/template/event/overall_header_body_before.html
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/styles/prosilver/template/event/overall_header_body_before.html
@@ -0,0 +1 @@
+
diff --git a/styles/prosilver/template/event/overall_header_head_append.html b/styles/prosilver/template/event/overall_header_head_append.html
new file mode 100644
index 0000000..5615e3c
--- /dev/null
+++ b/styles/prosilver/template/event/overall_header_head_append.html
@@ -0,0 +1 @@
+
diff --git a/styles/prosilver/template/event/overall_header_navigation_append.html b/styles/prosilver/template/event/overall_header_navigation_append.html
new file mode 100644
index 0000000..a6f77ea
--- /dev/null
+++ b/styles/prosilver/template/event/overall_header_navigation_append.html
@@ -0,0 +1 @@
+{L_MCHAT_TITLE}
diff --git a/styles/prosilver/template/jquery-1.8.3.min.js b/styles/prosilver/template/jquery-1.8.3.min.js
new file mode 100644
index 0000000..45477c0
--- /dev/null
+++ b/styles/prosilver/template/jquery-1.8.3.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v1.8.3 jquery.com | jquery.org/license */
+(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t a ",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML=" ",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML=" ";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="
",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r ",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="
",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML=" ",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/ ]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""," "],legend:[1,""," "],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""," "],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X ","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>$2>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {L_FONT_TINY}
+ {L_FONT_SMALL}
+ {L_FONT_NORMAL}
+
+ {L_FONT_LARGE}
+
+ {L_FONT_HUGE}
+
+
+
+
+
+
+
+
+
+ {L_MCHAT_CUSTOM_BBCODES}
+
+ {custom_tags.BBCODE_TAG}
+
+
+
+
+
\ No newline at end of file
diff --git a/styles/prosilver/template/mchat_body.html b/styles/prosilver/template/mchat_body.html
new file mode 100644
index 0000000..b62501f
--- /dev/null
+++ b/styles/prosilver/template/mchat_body.html
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class="mChatRowLimitCustom" style="height: {MCHAT_CUSTOM_HEIGHT}px;"class="mChatRowLimit" style="height: {MCHAT_INDEX_HEIGHT}px;">
+
+
+
+
+
+
+
+
+
+
{L_MCHAT_NOMESSAGE}
+
+
+
+
{L_MCHAT_ANNOUNCEMENT}: {MCHAT_STATIC_MESS}
+
+
+
+
+
+
+
+
+
+
{L_MCHAT_ENABLE}
+
+
+
+
+
+
+
+
+
+
+{L_WHO_IS_CHATTING}
+
+ {L_MCHAT_WHOIS_REFRESH_EXPLAIN} {L_MCHAT_REFRESHING}
+{L_LEGEND}: {LEGEND}
+
+
+
+
diff --git a/styles/prosilver/template/mchat_color.html b/styles/prosilver/template/mchat_color.html
new file mode 100644
index 0000000..74d833b
--- /dev/null
+++ b/styles/prosilver/template/mchat_color.html
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/styles/prosilver/template/mchat_no_avatars.html b/styles/prosilver/template/mchat_no_avatars.html
new file mode 100644
index 0000000..29813e8
--- /dev/null
+++ b/styles/prosilver/template/mchat_no_avatars.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/styles/prosilver/template/mchat_rules.html b/styles/prosilver/template/mchat_rules.html
new file mode 100644
index 0000000..9a6351a
--- /dev/null
+++ b/styles/prosilver/template/mchat_rules.html
@@ -0,0 +1,22 @@
+
+
+{L_MCHAT_HELP}
+
+
+
+ {MCHAT_RULES}
+
+
+ {rule.MCHAT_RULE}
+
+
+
+{L_CLOSE_WINDOW}
+
+
\ No newline at end of file
diff --git a/styles/prosilver/template/mchat_stats.html b/styles/prosilver/template/mchat_stats.html
new file mode 100644
index 0000000..2e8610c
--- /dev/null
+++ b/styles/prosilver/template/mchat_stats.html
@@ -0,0 +1,4 @@
+
+
+ {MCHAT_INDEX_USERS_COUNT} {L_MCHAT_ONLINE_EXPLAIN} {MCHAT_INDEX_USERS_LIST}
+
\ No newline at end of file
diff --git a/styles/prosilver/template/ucp_mchat.html b/styles/prosilver/template/ucp_mchat.html
new file mode 100644
index 0000000..926eb73
--- /dev/null
+++ b/styles/prosilver/template/ucp_mchat.html
@@ -0,0 +1,72 @@
+
+
+
+
+{L_TITLE}
+
+
+
+ {S_HIDDEN_FIELDS}
+
+ {S_FORM_TOKEN}
+
+
+
+
+
\ No newline at end of file
diff --git a/styles/prosilver/theme/images/add.swf b/styles/prosilver/theme/images/add.swf
new file mode 100644
index 0000000..5d8b6c2
Binary files /dev/null and b/styles/prosilver/theme/images/add.swf differ
diff --git a/styles/prosilver/theme/images/ban.gif b/styles/prosilver/theme/images/ban.gif
new file mode 100644
index 0000000..44166b1
Binary files /dev/null and b/styles/prosilver/theme/images/ban.gif differ
diff --git a/styles/prosilver/theme/images/bg_button.gif b/styles/prosilver/theme/images/bg_button.gif
new file mode 100644
index 0000000..03172ff
Binary files /dev/null and b/styles/prosilver/theme/images/bg_button.gif differ
diff --git a/styles/prosilver/theme/images/del.gif b/styles/prosilver/theme/images/del.gif
new file mode 100644
index 0000000..6577166
Binary files /dev/null and b/styles/prosilver/theme/images/del.gif differ
diff --git a/styles/prosilver/theme/images/del.swf b/styles/prosilver/theme/images/del.swf
new file mode 100644
index 0000000..e306cc4
Binary files /dev/null and b/styles/prosilver/theme/images/del.swf differ
diff --git a/styles/prosilver/theme/images/edit.gif b/styles/prosilver/theme/images/edit.gif
new file mode 100644
index 0000000..4e181da
Binary files /dev/null and b/styles/prosilver/theme/images/edit.gif differ
diff --git a/styles/prosilver/theme/images/error.gif b/styles/prosilver/theme/images/error.gif
new file mode 100644
index 0000000..42f9c13
Binary files /dev/null and b/styles/prosilver/theme/images/error.gif differ
diff --git a/styles/prosilver/theme/images/error.swf b/styles/prosilver/theme/images/error.swf
new file mode 100644
index 0000000..d05b7ef
Binary files /dev/null and b/styles/prosilver/theme/images/error.swf differ
diff --git a/styles/prosilver/theme/images/ip.gif b/styles/prosilver/theme/images/ip.gif
new file mode 100644
index 0000000..8cebf29
Binary files /dev/null and b/styles/prosilver/theme/images/ip.gif differ
diff --git a/styles/prosilver/theme/images/load.gif b/styles/prosilver/theme/images/load.gif
new file mode 100644
index 0000000..085ccae
Binary files /dev/null and b/styles/prosilver/theme/images/load.gif differ
diff --git a/styles/prosilver/theme/images/ok.gif b/styles/prosilver/theme/images/ok.gif
new file mode 100644
index 0000000..d17dd3e
Binary files /dev/null and b/styles/prosilver/theme/images/ok.gif differ
diff --git a/styles/prosilver/theme/images/paused.gif b/styles/prosilver/theme/images/paused.gif
new file mode 100644
index 0000000..bfc1085
Binary files /dev/null and b/styles/prosilver/theme/images/paused.gif differ
diff --git a/styles/prosilver/theme/mchat.css b/styles/prosilver/theme/mchat.css
new file mode 100644
index 0000000..9717454
--- /dev/null
+++ b/styles/prosilver/theme/mchat.css
@@ -0,0 +1,277 @@
+/**
+ *
+ * @package phpBB Extension - mChat
+ * @copyright (c) 2015 dmzx - http://www.dmzx-web.net
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+ *
+ */
+
+/* mChat
+------------ */
+div.mChatBG1 {
+ background: -webkit-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: -o-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: -moz-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ border: 1px solid #999999;
+ -webkit-border-radius: 6px;
+ -o-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ padding: 5px;
+ color: #333333;
+ margin-right: 1px;
+ overflow: hidden;
+}
+
+div.mChatBG2 {
+ background: -webkit-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: -o-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: -moz-linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ background: linear-gradient(#B6BFC4, #FFFFFF, #FFFFFF, #B6BFC4);
+ border: 1px solid #999999;
+ -webkit-border-radius: 6px;
+ -o-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ padding: 5px;
+ color: #444444;
+ margin-right: 1px;
+ text-align: left;
+ overflow: hidden;
+}
+div.mChatRowLimit {
+ overflow: auto;
+ width: 100%;
+}
+
+div.mChatRowLimitCustom {
+ overflow: auto;
+ width: 100%;
+}
+
+div.mChatPanel {
+ text-align: center;
+ padding: 3px;
+ clear: both;
+}
+
+input.mChatText {
+ cursor: text;
+ width: 50%;
+ background-color: #FFFFFF;
+ border: 1px solid #B4BAC0;
+ color: #333333;
+ padding: 5px 5px 3px 5px;
+ margin: 3px 0px 3px 5px;
+}
+
+input.mChatText:hover {
+ border-color: #11A3EA;
+}
+
+div.mChatHover:hover {
+ background-color: #F6F4D0;
+}
+
+div.mChatBodyFix {
+ width: 100% !important;
+ background-color: #E9F0F5 !important;
+}
+
+div.mChatStatic {
+ padding-left: 5px;
+ font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
+ text-align: left;
+ font-size: 1.1em;
+}
+
+div.mChatStats {
+ padding-left: 5px;
+ margin-top: 2px;
+ font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
+ text-align: left;
+ min-height: 1.3em;
+ font-size: 1.1em;
+ height: auto !important;
+}
+
+div.mChatRefresh {
+ padding-left: 5px;
+ font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif;
+ text-align: left;
+ font-size: 1.1em;
+ margin-top: 1.5em;
+ clear: both;
+}
+
+input.mChatColor {
+ width: 100%;
+ text-align: center;
+ background-color: #DEE3E7;
+ border-style: none;
+}
+
+div.mChatMessage {
+ padding: 3px;
+ font-size: 1.1em;
+ width: 98%;
+
+}
+
+a.mChatScriptLink {
+ text-decoration:none;
+}
+
+img.mChatImage{
+ vertical-align: middle;
+}
+
+img.mChatImageLoad {
+ vertical-align: middle;
+ cursor: wait;
+ display: none;
+}
+
+img.mChatImageOk {
+ vertical-align: middle;
+ cursor: help;
+}
+
+img.mChatImageHideImg {
+ vertical-align: middle;
+ cursor: help;
+ display: none;
+}
+
+div.mChatSound {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+}
+
+.mchat_alert {
+ color: #7E2217;
+ padding: 10px;
+}
+
+#mChatUserList {
+ display: none;
+ float: left;
+}
+
+.mChatAvatars {
+ float: left;
+ padding-right: 5px;
+}
+
+div.avatarMessage {
+ margin-left: 50px;
+ width: 90%;
+ margin-right: 5px;
+}
+
+.appriseOverlay
+ {
+ position:fixed;
+ top:0;
+ left:0;
+ background:rgba(0, 0, 0, 0.3);
+ display:none;
+ }
+.appriseOuter
+ {
+ background:#dcdee2;
+ border:1px solid #fff;
+ box-shadow:0px 3px 7px #333;
+ -moz-box-shadow:0px 3px 7px #333;
+ -webkit-box-shadow:0px 3px 7px #333;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+ border-radius:4px;
+ -khtml-border-radius:4px;
+ position:absolute;
+ z-index:99999999;
+ min-width:200px;
+ min-height:50px;
+ max-width:75%;
+ position:fixed;
+ display:none;
+ }
+.appriseInner
+ {
+ padding:20px;
+ color:#333;
+ text-shadow:0px 1px 0px #fff;
+ font-weight: bold;
+ }
+.appriseInner button
+ {
+ border:1px solid #666666;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ border-radius:3px;
+ -khtml-border-radius:3px;
+ background: -moz-linear-gradient(100% 100% 90deg, #eee, #d5d5d5);
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eee), to(#d5d5d5));
+ background: -webkit-linear-gradient(#eee, #d5d5d5);
+ background: -o-linear-gradient(#eee, #d5d5d5);
+ color:#000000;
+ font-size:12px;
+ font-weight:bold;
+ padding:4px 10px;
+ margin:0 3px;
+ text-shadow:0px 1px 0px #fff;
+ cursor:pointer;
+ box-shadow:0px 1px 2px #ccc;
+ -moz-box-shadow:0px 1px 2px #ccc;
+ -webkit-box-shadow:0px 1px 2px #ccc;
+ }
+.appriseInner button:hover
+ {
+ color:#d85054;
+ }
+.aButtons, .aInput
+ {
+ margin:20px 10px 0px 10px;
+ text-align:center;
+ }
+.aTextbox
+ {
+ border:1px solid #aaa;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+ border-radius:4px;
+ -khtml-border-radius:4px;
+ box-shadow:0px 1px 0px #fff;
+ -moz-box-shadow:0px 1px 0px #fff;
+ -webkit-box-shadow:0px 1px 0px #fff;
+ width:180px;
+ font-size:12px;
+ font-weight:bold;
+ padding:5px 10px;
+ }
+.no-rgba .appriseOverlay{
+ opacity: .30;
+ filter: alpha(opacity = 30) !important;
+ background: #000;
+ zoom: 1;
+}
+.no-borderradius .appriseOuter{
+ border:1px solid #888;
+}
+.appriseOverlay {
+background-color:#222222;
+border:medium none;
+cursor:wait;
+height:100%;
+left:0;
+margin:0;
+padding:0;
+position:fixed;
+top:0;
+width:100%;
+z-index:1000;
+filter:alpha(opacity=70);
+opacity:0.70;
+}
\ No newline at end of file
diff --git a/ucp/ucp_mchat_info.php b/ucp/ucp_mchat_info.php
new file mode 100644
index 0000000..88ec10f
--- /dev/null
+++ b/ucp/ucp_mchat_info.php
@@ -0,0 +1,28 @@
+ '\dmzx\mchat\ucp\ucp_mchat_module',
+ 'title' => 'UCP_MCHAT_CONFIG',
+ 'version' => '1.3.8',
+ 'modes' => array(
+ 'configuration' => array(
+ 'title' => 'UCP_MCHAT_CONFIG',
+ 'auth' => 'ext_dmzx/mchat && acl_u_mchat_use',
+ 'cat' => array('UCP_MCHAT_CONFIG')),
+ ),
+ );
+ }
+}
diff --git a/ucp/ucp_mchat_module.php b/ucp/ucp_mchat_module.php
new file mode 100644
index 0000000..903d09b
--- /dev/null
+++ b/ucp/ucp_mchat_module.php
@@ -0,0 +1,112 @@
+functions_mchat = $phpbb_container->get('dmzx.mchat.functions_mchat');
+
+ // $user->add_lang('mods/mchat_lang');
+
+ $submit = (isset($_POST['submit'])) ? true : false;
+ $error = $data = array();
+
+ switch ($mode)
+ {
+ case 'configuration':
+
+ $data = array(
+ 'user_mchat_index' => $request->variable('user_mchat_index', (bool) $user->data['user_mchat_index']),
+ 'user_mchat_sound' => $request->variable('user_mchat_sound', (bool) $user->data['user_mchat_sound']),
+ 'user_mchat_stats_index' => $request->variable('user_mchat_stats_index', (bool) $user->data['user_mchat_stats_index']),
+ 'user_mchat_topics' => $request->variable('user_mchat_topics', (bool) $user->data['user_mchat_topics']),
+ 'user_mchat_avatars' => $request->variable('user_mchat_avatars', (bool) $user->data['user_mchat_avatars']),
+ 'user_mchat_input_area' => $request->variable('user_mchat_input_area', (bool) $user->data['user_mchat_input_area']),
+ );
+
+ add_form_key('ucp_mchat');
+
+ if ($submit)
+ {
+ if (!check_form_key('ucp_mchat'))
+ {
+ $error[] = 'FORM_INVALID';
+ }
+
+ if (!sizeof($error))
+ {
+ $sql_ary = array(
+ 'user_mchat_index' => $data['user_mchat_index'],
+ 'user_mchat_sound' => $data['user_mchat_sound'],
+ 'user_mchat_stats_index' => $data['user_mchat_stats_index'],
+ 'user_mchat_topics' => $data['user_mchat_topics'],
+ 'user_mchat_avatars' => $data['user_mchat_avatars'],
+ 'user_mchat_input_area' => $data['user_mchat_input_area'],
+ );
+
+ if (sizeof($sql_ary))
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE user_id = ' . (int) $user->data['user_id'];
+ $db->sql_query($sql);
+ }
+
+ meta_refresh(3, $this->u_action);
+ $message = $user->lang['PROFILE_UPDATED'] . ' ' . sprintf($user->lang['RETURN_UCP'], '', ' ');
+ trigger_error($message);
+ }
+
+ // Replace "error" strings with their real, localised form
+ $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
+ }
+ if (($mchat_cache = $cache->get('_mchat_config')) === false)
+ {
+ $this->functions_mchat->mchat_cache();
+ }
+ $mchat_cache = $cache->get('_mchat_config');
+
+ $template->assign_vars(array(
+ 'ERROR' => (sizeof($error)) ? implode(' ', $error) : '',
+
+ 'S_DISPLAY_MCHAT' => $data['user_mchat_index'],
+ 'S_SOUND_MCHAT' => $data['user_mchat_sound'],
+ 'S_STATS_MCHAT' => $data['user_mchat_stats_index'],
+ 'S_TOPICS_MCHAT' => $data['user_mchat_topics'],
+ 'S_AVATARS_MCHAT' => $data['user_mchat_avatars'],
+ 'S_INPUT_MCHAT' => $data['user_mchat_input_area'],
+ 'S_MCHAT_TOPICS' => $config['mchat_new_posts'],
+ 'S_MCHAT_INDEX' => ($config['mchat_on_index'] || $config['mchat_stats_index']) ? true : false,
+ 'S_MCHAT_AVATARS' => $mchat_cache['avatars'],
+ ));
+ break;
+
+ }
+
+ $template->assign_vars(array(
+ 'L_TITLE' => $user->lang['UCP_PROFILE_MCHAT'],
+ 'S_UCP_ACTION' => $this->u_action
+ ));
+
+ // Set desired template
+ $this->tpl_name = 'ucp_mchat';
+ $this->page_title = 'UCP_PROFILE_MCHAT';
+ }
+// $this->page_title = 'UCP_PROFILE_MCHAT';
+
+}